SELECT t1.c0, t1.c1::VARCHAR(16777216), t1.c2::VARCHAR(16777216), t1.c3::VARCHAR(16777216), t1.c4::VARCHAR(16777216) FROM (SELECT (t0."PERSONID"::NUMBER(38, 0))::DOUBLE, t0."LASTNAME"::VARCHAR(255), t0."FIRSTNAME"::VARCHAR(255), t0."ADDRESS"::VARCHAR(255), t0."CITY"::VARCHAR(255) FROM "PERSONS_SNW" AS t0) AS t1 (c0, c1, c2, c3, c4) WHERE c0 = 1
Above sql is failing with SQL compilation error: error line 1 at position 7 invalid identifier 'T1.C0'
Why can't we append select alias name with column alias name?
SELECT c0, c1::VARCHAR(16777216), c2::VARCHAR(16777216), c3::VARCHAR(16777216), c4::VARCHAR(16777216) FROM (SELECT (t0."PERSONID"::NUMBER(38, 0))::DOUBLE, t0."LASTNAME"::VARCHAR(255), t0."FIRSTNAME"::VARCHAR(255), t0."ADDRESS"::VARCHAR(255), t0."CITY"::VARCHAR(255) FROM "PERSONS_SNW" AS t0) AS t1 (c0, c1, c2, c3, c4) WHERE c0 = 1
It seems Snowflake can not handle column aliases for subqueries (for now). Maybe you can submit a support ticket about it. Not sure if it's a bug or it's not supported intentionally.
-- not working
SELECT t1.c0 FROM
(SELECT v1,v2 from testy) as t1(c0, c1);
-- working if you define alias in subquery
SELECT t1.c0 FROM
(SELECT v1 c0, v2 from testy) as t1;
-- working if you use CTE instead of subquery
with t1 (c0, c1) as
(SELECT * from testy)
SELECT t1.c0 FROM t1;
You may define alias in subquery or you may use CTE instead of subquery.
Related
Imagine we have a complicated multiline query from 2 tables
A (pkA, a1, a2)
B (pkB, fkA, b1, b2)
and we have a query which we have not added table prefix for columns:
select pkA, a1, a2, b1, bb2,....
from A
inner join B on pkA = fkA
where a1 = 1 and a2 = 2
order by a1
Now we want to add self reference column fkSelfA to table A, and we then want to change the self reference join to query, the query should all change to:
select A.pkA, A.a1, A.a2, b1, bb2, SelfA.A1 as SelfA1
from A
inner join B on pkA = fkA
left join A SelfA on SelfA.pkA = A.fkSelfA
where A.a1 = 1 and A.a2 = 2
order by A.a1
As we can see we have to change all the query and add "A." to everywhere we have used table A columns.
I'm wondering if there is or will be any feature that ignores column names of a table in joins so we can easily add the join without being worried about ambiguous column names foe example:
select pkA,a1,a2,b1,bb2,SelfA.A1 as SelfA1
from A inner join B ON pkA=fkA
LEFT JOIN Ignore A SelfA ON SelfA.pkA=A.fkSelfA
where a1=1 and a2=2
order by a1
Well, you could do this:
SELECT pkA, a1, a2, b1, bb2, SelfA1
FROM A INNER JOIN B ON pkA=fkA
OUTER APPLY (
SELECT SelfA.A1 AS SelfA1
FROM A SelfA
WHERE SelfA.pkA=A.fkSelfA
) X
WHERE a1=1 AND a2=2
ORDER BY a1
However, it's better to prefix all columns with table aliases. To help you with that, you could use a tool like Red Gate SQLPrompt.
I am trying to execute this query:
DELETE from TABLE1A
WHERE X IN
(SELECT A.X FROM
(SELECT X, r1.Y, r2.Y, DENSE_RANK() OVER (PARTITION by r1.Y, r2.Y ORDER by X) as RANK
FROM TABLE1B r0
INNER JOIN TABLE1A r1 on r0.X = r1.X
INNER JOIN TABLE1A r2 on r0.X = r2.X
WHERE r1.Y = foo and r2.Y = bar
) AS A WHERE A.RANK > 1
);
After executing it, am getting the error: SQL Error [268] [HY000]: SAP DBTech JDBC: [268] (at 63): column ambiguously defined: X
What could possibly go wrong in that query?
Tables R1 and R2 both seem to have columns named X, but in the ORDER BY part on the window function you don’t specify which of these columns should be used; thus the error message.
I have written a variety of SQL queries for a university's large oracle database. The output is a list of available degrees and associated information.
I now need to find a way to show what has changed between versions (based on a column called 'version'. New versions are created when data is changed)
How might I highlight differences based on the output of my selects in the queries?
This is the smallest query I can show as an example:
SELECT
-- DETAILS
b.programmeid,
b.programmecode AS course_udc,
b.programmeversion AS version,
b.externalversion AS external_version,
b.programme AS full_title,
-- OUTCOMES
b.programmeoutcomeid AS outcome_number,
b.outcomedesc AS outcome_description,
b.programmeoutcometypeid AS graduate_attribute_link
FROM
(
SELECT
-- DETAILS
a.programmeid,
a.programmecode,
a.programmeversion,
a.externalversion,
a.programme,
-- OUTCOMES
a.programmeoutcomeid,
a.outcomedesc,
a.programmeoutcometypeid
FROM
document_application.dmn_domains d,
(
SELECT
-- DETAILS
ed.dmn_cuid,
p.programmeid,
p.programmecode,
p.programmeversion,
p.externalversion,
p.programme,
-- OUTCOMES
plo.programmeoutcomeid,
( dbms_lob.substr(pso.suboutcomedesc,4000,1) ) AS outcomedesc,
plo.programmeoutcometypeid
FROM
document_application.programmes p
INNER JOIN document_application.edm_entitydomains ed ON p.cuid = ed.entitycuid -- Join with EDM_ENTITYDOMAINS
INNER JOIN document_application.programmeoutcomes plo ON p.programmeid = plo.programmeid -- Join with PROGRAMMEOUTCOMES
INNER JOIN document_application.programmesuboutcomes pso ON plo.programmeoutcomeid = pso.suboutcomeid -- Join with PROMGRAMMESUBOUTCOMES
WHERE
p.programmecode IN (
SELECT
p.programmecode
FROM
document_application.programmes p
GROUP BY
p.programmecode
HAVING
COUNT(*) > 1
)
AND ed.ett_code = 'P'
) a
WHERE
a.dmn_cuid = d.cuid
) b
ORDER BY
course_udc,
version
As you can see, I'll be using a variety of tables.
The b.programmeversion is the version column from which I need to show changes between.
This is an example of the output
output
To show what changed between one version and the other, you can use the MINUS clause. Say you want to see what changed at the level of columns c1, c2, c3 between v1 and v2:
was in version v1, but not any more in v2
select c1, c2, c3 from result_set where VERSION='v1'
minus select c1, c2, c3 from result_set where VERSION='v2'
new in version v2, was not in v1
select c1, c2, c3 from result_set where VERSION='v2'
minus select c1, c2, c3 from result_set where VERSION='v1'
hope this helps
I have a query like below. What i want is to select null or blank if there is no records for a particular value in the IN statement.
There values are entered by user.
select system_code, max(last_update_timestamp) as [last_update_timestamp]
from table_name
where system_code in ('E1','E2','E3')
Group by system_code
E1 has 100 records
E2 has 20 records
E3 has no records
Using the above query i am getting this result :
Sytem_code last_update_timestamp
E1 '2014-09-28 11:35:10.647'
E2 '2014-09-28 11:35:10.647'
Expected reuslt
Sytem_code last_update_timestamp
E1 '2014-09-28 11:35:10.647'
E2 '2014-09-28 11:35:10.647'
E3 Null or Blank
Any help will be appreciated.
Use Table Value Constructor to build an in-line table containing all values of the IN operator. Then LEFT JOIN your query to this table:
SELECT x.sc, [last_update_timestamp]
FROM (VALUES ('E1'), ('E2'), ('E3')) AS x(sc)
LEFT JOIN (
SELECT system_code, max(last_update_timestamp) as [last_update_timestamp]
FROM table_name
WHERE system_code IN ('E1','E2','E3')
GROUP BY system_code ) AS t ON x.sc = t.system_code
Demo here
SELECT x.sc, max(last_update_timestamp) as [last_update_timestamp]
FROM (VALUES ('E1'), ('E2'), ('E3')) AS x(sc)
LEFT JOIN table_name
ON table_name.system_code = x.sc
GROUP BY x.sc
That query works for most DB engines
select tmp.system_code, max(table_name.last_update_timestamp) as [last_update_timestamp]
from
(
select 'E1' as system_code
union all
select 'E2'
union all
select 'E3'
) tmp
left join table_name on tmp.system_code = table_name.system_code
and table_name.system_code in ('E1','E2','E3')
Group by tmp.system_code
I have one table vwuser. I want join this table with the table valued function fnuserrank(userID). So I need to cross apply with table valued function:
SELECT *
FROM vwuser AS a
CROSS APPLY fnuserrank(a.userid)
For each userID it generates multiple records. I only want the last record for each empid that does not have a Rank of Term(inated). How can I do this?
Data:
HistoryID empid Rank MonitorDate
1 A1 E1 2012-8-9
2 A1 E2 2012-9-12
3 A1 Term 2012-10-13
4 A2 E3 2011-10-09
5 A2 TERM 2012-11-9
From this 2nd record and 4th record must be selected.
In SQL Server 2005+ you can use this Common Table Expression (CTE) to determine the latest record by MonitorDate that doesn't have a Rank of 'Term':
WITH EmployeeData AS
(
SELECT *
, ROW_NUMBER() OVER (PARTITION BY empId, ORDER BY MonitorDate DESC) AS RowNumber
FROM vwuser AS a
CROSS APPLY fnuserrank(a.userid)
WHERE Rank != 'Term'
)
SELECT *
FROM EmployeeData AS ed
WHERE ed.RowNumber = 1;
Note: The statement before this CTE will need to end in a semi-colon. Because of this, I have seen many people write them like ;WITH EmployeeData AS...
You'll have to play with this. Having trouble mocking your schema on sqlfiddle.
Select bar.*
from
(
SELECT *
FROM vwuser AS a
CROSS APPLY fnuserrank(a.userid)
where rank != 'TERM'
) foo
left join
(
SELECT *
FROM vwuser AS b
CROSS APPLY fnuserrank(b.userid)
where rank != 'TERM'
) bar
on foo.empId = bar.empId
and foo.MonitorDate > bar.MonitorDate
where bar.empid is null
I always need to test out left outers on dates being higher. The way it works is you do a left outer. Every row EXCEPT one per user has row(s) with a higher monitor date. That one row is the one you want. I usually use an example from my code, but i'm on the wrong laptop. to get it working you can select foo., bar. and look at the results and spot the row you want and make the condition correct.
You could also do this, which is easier to remember
SELECT *
FROM vwuser AS a
CROSS APPLY fnuserrank(a.userid)
) foo
join
(
select empid, max(monitordate) maxdate
FROM vwuser AS b
CROSS APPLY fnuserrank(b.userid)
where rank != 'TERM'
) bar
on foo.empid = bar.empid
and foo.monitordate = bar.maxdate
I usually prefer to use set based logic over aggregate functions, but whatever works. You can tweak it also by caching the results of your TVF join into a table variable.
EDIT:
http://www.sqlfiddle.com/#!3/613e4/17 - I mocked up your TVF here. Apparently sqlfiddle didn't like "go".
select foo.*, bar.*
from
(
SELECT f.*
FROM vwuser AS a
join fnuserrank f
on a.empid = f.empid
where rank != 'TERM'
) foo
left join
(
SELECT f1.empid [barempid], f1.monitordate [barmonitordate]
FROM vwuser AS b
join fnuserrank f1
on b.empid = f1.empid
where rank != 'TERM'
) bar
on foo.empId = bar.barempid
and foo.MonitorDate > bar.barmonitordate
where bar.barempid is null