I have a table:
num type flag
--- ---- ----
11 A 1
12 A 1
13 A 1
14 A 1
15 A 1
12 B 2
13 B 2
How would I write a query to get the following result:
num type flag
--- ---- ----
11 A 1
14 A 1
15 A 1
select num
from your_table
where num not in
(
select num
from your_table
where type = 'B'
)
Try to use not exists as below
select *
from tab t
where t.type = 'A'
and not exists
(
select 1
from tab t1
where t1.type = 'B'
and t1.num=t.num
)
Related
select data by passing a value in where clause if the value match then return matches data otherwise return all data.
Consider following example
ID Name
1 ABC
2 DEF
3 GHI
4 JKL
When pass id = 1 the return row 1 when pass null value or 0 then return all data.
You can use analytical function as follows:
SELECT * FROM
(SELECT T.*,
SUM(CASE WHEN T.ID = <YOUR_VALUE(0,1,NULL, or any)> THEN 1 ELSE 0 END) OVER () AS SM
FROM YOUR_TABLE T)
WHERE SM = 0 OR ID = <YOUR_VALUE(0,1,NULL, or any)>
You need to replace <YOUR_VALUE(0,1,NULL)> with a value that you want to pass.
For values 0 and 1, results are as follows:
SQL> SELECT * FROM
2 (SELECT T.*,
3 SUM(CASE WHEN T.ID = 0 THEN 1 ELSE 0 END) OVER () AS SM
4 FROM YOUR_TABLE T)
5 WHERE SM = 0 OR ID = 0 ;
ID NAM SM
---------- --- ----------
1 ABC 0
2 DEF 0
3 GHI 0
4 JKL 0
SQL>
SQL>
SQL> SELECT * FROM
2 (SELECT T.*,
3 SUM(CASE WHEN T.ID = 1 THEN 1 ELSE 0 END) OVER () AS SM
4 FROM YOUR_TABLE T)
5 WHERE SM = 0 OR ID = 1;
ID NAM SM
---------- --- ----------
1 ABC 1
SQL>
You can use not exists:
select t.*
from t
where id = 1 or
not exists (select 1 from t t2 where t2.id = 1);
Or as a passed-in value:
select t.*
from t
where id = :input or
not exists (select 1 from t t2 where t2.id = :input);
Note that this works for NULL values as well, because the where in the subquery would evaluate to NULL if :input is NULL.
I have following table with data
id | COL1
=========
1 | b
2 | z
3 | b
4 | c
5 | b
6 | a
7 | b
8 | c
9 | a
So i know ID of 'z' (ID = 2) in the table and i will call it Z_ID.
I need to retrieve rows between 'a' and 'c' (including 'a' and 'c').
It must be first 'a' that comes after Z_ID.
'c' must come after Z_ID and after 'a' that i found previously.
Result that i am seeking is:
id | COL1
=========
6 | a
7 | b
8 | c
My SELECT looks like this
SELECT *
FROM table
WHERE id >= (
SELECT MIN(ID)
FROM table
WHERE COL1 = 'a' AND ID > 2
)
AND id <= (
SELECT MIN(ID)
FROM table
WHERE COL1 = 'c'AND ID > 2 and ID > (
SELECT MIN(ID)
FROM table
WHERE COL1 = 'a' AND ID > 2
)
)
I am getting the result that i want. But i am concerned about performance because i am using same subquery two times. Is there a way to reuse a result from first subquery?
Maybe there is cleaner way to get the result that i need?
Use a CTE which will return only once the result of the subquery that you use twice:
WITH cte AS (
SELECT MIN(ID) minid
FROM tablename
WHERE COL1 = 'a' AND ID > 2
)
SELECT t.*
FROM tablename t CROSS JOIN cte c
WHERE t.id >= c.minid
AND t.id <= (
SELECT MIN(ID)
FROM tablename
WHERE COL1 = 'c' and ID > c.minid
)
In your 2nd query's WHERE clause:
WHERE COL1 = 'c'AND ID > 2 and ID > (...
the condition AND ID > 2 is not needed because the next condition and ID > (... makes sure that ID will be greater than 2 so I don't use it either in my code.
See the demo.
Results:
| id | COL1 |
| --- | ---- |
| 6 | a |
| 7 | b |
| 8 | c |
You can use window functions for this:
select t.*
from (select t.*,
min(case when id > min_a_id and col1 = 'c' then id end) over () as min_c_id
from (select t.*,
min(case when col1 = 'a' then id end) over () as min_a_id
from (select t.*,
min(case when col1 = 'z' then id end) over () as z_id
from t
) t
where id > z_id
) t
) t
where id >= min_a_id and id < min_c_id;
I have a table like this.
TABLE-1
id Code
-----------------
1 N188
1 N1Z2
1 N222
2 N189
2 N1Z2
2 N1Z3
3 N188
3 A123
3 B321
4 N188
4 A333
4 B444
I want to select id and code only code has N188.Result should like this:
TABLE-2
id Code
---------------
1 N188
1 N1Z2
1 N222
3 N188
3 A123
3 B321
4 N188
4 A333
4 B444
How can I write sql for this in SQL Server?
Thanks
You can use EXISTS for this:
SELECT id, code
FROM table1 t
WHERE EXISTS (
SELECT 1
FROM table1 t2
WHERE t.id = t2.id
AND t2.Code = 'N188'
)
Condensed SQL Fiddle Demo
Using INNER JOIN
SELECT *
FROM tablename A
JOIN (SELECT id
FROM tablename
WHERE code = 'N188') B
ON a.id = b.id
Here is an alternative method that uses window functions:
select id, code
from (select t.*,
sum(case when code = 'N188' then 1 else 0 end) over (partition by id) as cnt_n188
from table t
) t
where cnt_n188 > 0;
if I have a table with values like this:
ID SUBID FLAG
-----------------
1 1 1
1 2 (null)
2 3 1
2 3 (null)
3 4 1
4 5 1
4 6 (null)
5 7 0
6 8 (null)
7 9 1
and I would like to get all the ID's where 'FLAG' is only set to 1, so in this case the query would return
ID SUBID FLAG
-----------------
3 4 1
7 9 1
How can I achieve this?
try this:
SELECT * FROM flags where flag=1
and ID NOT in( SELECT ID FROM flags where flag !=1 OR flag IS NULL)
I don't have a db2 instance to test on but this might work:
select t1.id, t1.subid, t1.flag
from yourtable t1
inner join
(
select id
from yourtable
group by id
having count(id) = 1
) t2
on t1.id = t2.id
where t1.flag = 1;
I've the below table
ID TYPE
--- ----
1 P
1 W
2 P
3 W
4 W
4 X
5 P
6 null
I need a new table to be created like the one below
ID Count of Type Code
-- -------------- -------
1 2 null
2 1 P
3 1 W
4 2 null
5 1 P
6 0 null
1st col ---> ID
2nd col ---> count of "type" for an ID
3rd col ---> if count(type) = 1 then TYPE
else null
Kindly help me in writing an ORACLE SQL query
You could use a subquery with the max function to get a value for the code and then use that in a case statement to get the value in your final query only when the count=1.
select id, cnt, case when cnt=1 then maxtype else null end as code
from
(select id, count(*) as cnt, max(type) as maxtype
from t1
group by id) t2