I'm getting the following error when running the below in the snowflake:
'Unexpected Select statement'
Here is my SQL
SELECT * FROM ABC
WHERE DR2NB NOT IN ( SELECT DR2NB FROM ABC WHERE FLAG='TRUE' )
ORDER BY DR2NB
CREATE OR REPLACE TABLE ABC (DR2NB NUMBER, FLAG VARCHAR);
INSERT INTO ABC VALUES(1,'TRUE'),(2,'FALSE'),(3,'TRUE'),(4,'FALSE'),(1,'TRUE'),(2,'FALSE'),(3,'TRUE'),(4,'FALSE');
SELECT * FROM ABC WHERE DR2NB NOT IN ( SELECT DR2NB FROM ABC WHERE FLAG='TRUE' ) ORDER BY DR2NB;
You can achieve the desired result by using the below query too:
SELECT * FROM ABC WHERE FLAG!='TRUE' ORDER BY DR2NB;
It is difficult to suggest changes without examples of the data, but I would suggest structuring the subquery like this:
With x as(SELECT DR2NB FROM ABC WHERE FLAG='TRUE' )
SELECT *
FROM ABC
WHERE
DR2NB NOT IN x
ORDER BY DR2NB;
Reference:
https://docs.snowflake.net/manuals/sql-reference/constructs/with.html
https://docs.snowflake.net/manuals/sql-reference/operators-subquery.html
https://docs.snowflake.net/manuals/user-guide/querying-subqueries.html
Related
I need to write a Sql Satement that gets passed any valid SQL subquery, and return the the resultset, WITH HEADERS.
Somehow i need to interrogate the resultset, get the fieldnames and return them as part of a "Union" with the origional data, then pass the result onwards for exporting.
Below my attempt: I have a Sub-Query Callled "A", wich returns a dataset and i need to query it for its fieldnames. ?ordinally maybe?
select A.fields[0].name, A.fields[1].name, A.fields[2].name from
(
Select 'xxx1' as [Complaint Mechanism] , 'xxx2' as [Actual Achievements]
union ALL
Select 'xxx3' as [Complaint Mechanism] , 'xxx4' as [Actual Achievements]
union ALL
Select 'xxx5' as [Complaint Mechanism] , 'xxx6' as [Actual Achievements] ) as A
Any pointers would be appreciated (maybe i am just missing the obvious...)
The Resultset should look like the table below:
F1 F2
--------------------- ---------------------
[Complaint Mechanism] [Actual Achievements]
xxx1 xxx2
xxx3 xxx4
xxx5 xxx6
If you have a static number of columns, you can put your data into a temp table and then query tempdb.sys.columns to get the column names, which you can then union on top of your data. If you will have a dynamic number of columns, you will need to use dynamic SQL to build your pivot statement but I'll leave that up to you to figure out.
The one caveat here is that all data under your column names will need to be converted to strings:
select 1 a, 2 b
into #a;
select [1] as FirstColumn
,[2] as SecondColumn
from (
select column_id
,name
from tempdb.sys.columns
where object_id = object_id('tempdb..#a')
) d
pivot (max(name)
for column_id in([1],[2])
) pvt
union all
select cast(a as nvarchar(100))
,cast(b as nvarchar(100))
from #a;
Query Results:
| FirstColumn | SecondColumn |
|-------------|--------------|
| a | b |
| 1 | 2 |
I have a table like this:
SchoolName|SchoolID
--------------------
School A |x
School B |x
School C |y
School D |z
School D |z
There are actually more columns, including a unique ID. The above is just for brevity.
What I need to do is select all columns, where the SchoolID occurs more than once, but only if the corresponding value in the SchoolName column doesn't.
So I'd like get all columns for the rows with School A and School B, but not the School C and School D rows.
The db is MS SQL 2008 R2.
The original question was terribly confused, hopefully I've managed to rephrase it correctly now!
You can use window version of COUNT to count SchoolID and SchoolName occurences:
SELECT *
FROM (
SELECT *,
COUNT(*) OVER (PARTITION BY SchoolID) AS cntSchoolID,
COUNT(*) OVER (PARTITION BY SchoolID, SchoolName) AS cntSchoolName
FROM mytable ) t
WHERE t.cntSchoolID > 1 AND t.cntSchoolName = 1
SQL Fiddle Demo
So do you want something like this?
SELECT A.*
FROM yourTable A
CROSS APPLY (
SELECT TOP 1 NULL col
FROM yourTable
WHERE A.SchoolID = SchoolID
AND A.SchoolName = SchoolName
GROUP BY SchoolID,SchoolName
HAVING COUNT(*) > 1
) CA
I would build a list of all the schoolnames that repeat, and all the schoolids that repeat, and then pull all of the rows where the schoolname or the schoolid match:
select
*
from
mytable
where
(schoolname in
(
select schoolname
from
mytable
group by schoolname
having count (*) > 1)
OR
schoolid in
(
select
schoolid
from
mytable
group by schoolid
having count (*) > 1)
)
Ugly, but I think it gives you your desired result.
SQL Fiddle
I'm stuck with a query which should be pretty simple but, for reasons unknown, my brain is not playing ball here ...
Table:
id(int) | strategy (varchar) | value (whatever)
1 "ABC" whatevs
2 "ABC" yeah
3 "DEF" hello
4 "DEF" kitty
5 "QQQ" hurrr
The query should select ALL rows grouped on strategy but only one row per strategy - the one with the higest id.
In the case above, it should return rows with id 2, 4 and 5
SELECT id, strategy , value
FROM (
SELECT id, strategy , value
,ROW_NUMBER() OVER (PARTITION BY strategy ORDER BY ID DESC) rn
FROM Table_Name
) Sub
WHERE rn = 1
Working SQL FIDDLE
You can use window function to get the solution you want. Fiddle here
with cte as
(
select
rank()over(partition by strategy order by id desc) as rnk,
id, strategy, value from myT
)
select id, strategy, value from
cte where rnk = 1;
Try this:
SELECT T2.id,T1.strategy,T1.value
FROM TableName T1
INNER JOIN
(SELECT MAX(id) as id,strategy
FROM TableName
GROUP BY strategy) T2
ON T1.id=T2.id
Result:
ID STRATEGY VALUE
2 ABC yeah
4 DEF kitty
5 QQQ hurrr
See result in SQL Fiddle.
SELECT id, strategy , value
FROM (
SELECT id, strategy , value
,MAX(id) OVER (PARTITION BY strategy) MaxId
FROM YourTable
) Sub
WHERE id=MaxId
You may try this one as well:
SELECT id, strategy, value FROM TableName WHERE id IN (
SELECT MAX(id) FROM TableName GROUP BY strategy
)
Bit depends on your data, you might get results faster with it as it does not do sorting, but by the other hand it uses IN, which can slow you down if there is many 'strategies'
Is it possible to access a temporary column that was defined in a query for a Common Table Expression? Say I have
select * from myTable
;with cte as
(
select
*, Salary * 4 as FourTimesSalary
from
Employees
where
Name = #name
and ID >= 100
)
Is there a way to use the temporary column FourTimesSalary when querying cte like so?
select top 2 *
from cte
order by FourTimesSalary, Name
TIA.
Yes you can do that. Example:
with temp as
(
select 1 as id, 2*4 as val
UNION
select 2 as id, 3*4 as val
)
SELECT * FROM temp ORDER BY VAL desc
Your example looks fine, did you get an error when you tried that or something?
Can I write the T-SQL like below
select *
FROM (select *
from TableA
where FieldA = 1
)
where FieldB > 10
which means I want to query from the results of another query.
Yes you can
select *
FROM ( select * from TableA where FieldA=1 ) sub
where FieldB > 10
Just remember to give the sub select an alias.
Yes, you can do that.
If you want to separate out your sub-queries you can also use Common Table Expressions (CTE's) which help make your code more readable:
WITH Foo (FieldA, FieldB, FieldC) AS
(
SELECT FieldA, FieldB, FieldC
FROM TableA
WHERE FieldA=1
)
SELECT *
FROM Foo
WHERE FieldB > 10
The downside is you will have to explicitly name your columns. However, this actually makes your code faster so it's not always a bad thing.