I have a table like this:
Id,Code, (some more columns)
1, c
1, a
1, b
1, b
1, b
2, a -- the desired row
3, b
3, c
3, a
3, a
I want to get one Id (or all) which have only been associated with 'a' and not 'b' and 'c'. How do I do this ?
What i tried just now:
select *
from
(
select Id, count(case when Code='a' then 0 else 1 end) c
from tbl
group by Id
)
where c = 0
Why does this not work ?
This will get you the list of Id values which are associated only with codes of 'a'.
select Id
from tbl
group by Id
having max(case when Code='a' then 0 else 1 end) = 0
See this fiddle for a live demo.
Related
I have the following table:
CREATE TABLE TABLE1 (
ID,
status,
timestamp
)
I would like to check for ID's that have status A, but also for ID's that have status B AND status C. I would like them to be placed into a count somewhat as follows:
SELECT
ID
,SUM(CASE WHEN status = 'A' then 1
WHEN
-- something like the following:
status = 'B' and (status = 'C' AND [timestamp of C] > [timestamp of B]) then 1
else 0 END) as SUCCESS
FROM TABLE1
GROUP BY ID
Do I need a self join here? How do I get the IDs that have this status = B & C with a timestampB < timestampC conditional?
Example table:
INSERT INTO TABLE1(ID, status, timestamp)
VALUES(1, A, 5)
VALUES(2,B, 3)
VALUES(2, D, 5)
VALUES(3, A, 5)
VALUES(4, B, 9)
VALUES(4,C,10)
Results should be:
1, 1
2, 0
3, 1
4, 1
If you want ids that have A and whose timestamp for B is less than C, then use:
select id
from t
group by id
having sum(case when status = 'A' then 1 else 0 end) > 0 and
min(case when status = 'B' then timestamp end) < max(case when status = 'C' then timestamp end)
EDIT:
select id,
(case when sum(case when status = 'A' then 1 else 0 end) > 0 and
min(case when status = 'B' then timestamp end) < max(case when status = 'C' then timestamp end)
then 1 else 0
end) as success_flag
from t
group by id
i want to select row on condition based on column values in sql server please check below example with required result.
WITH allData
AS (
select mlid=1,value=0,checkid=1
union all
select mlid=2,value=6,checkid=2
union all
select mlid=3,value=6,checkid=1
union all
select mlid=4,value=0,checkid=2
)
select * from allData
Result
Mlid Value checked
1 0 1
2 6 2
3 6 1
4 0 2
required result -->
condition:- if checked column values is 1 and values column is 0 than display checked values values 2 rows only
either display checked column values 1
like below result
Mlid value checked
2 6 2
3 6 1
This will work for your sample data, but would fail for pretty much anything else?
WITH allData AS (
SELECT MLID = 1, [VALUE] = 0, CHECKID = 1
UNION ALL
SELECT MLID = 2, [VALUE] = 6, CHECKID = 2
UNION ALL
SELECT MLID = 3, [VALUE] = 6, CHECKID = 1
UNION ALL
SELECT MLID = 4, [VALUE] = 0, CHECKID = 2)
SELECT
CASE WHEN a1.CHECKID = 1 AND a1.VALUE = 0 THEN a2.MLID ELSE a1.MLID END AS MLID,
CASE WHEN a1.CHECKID = 1 AND a1.VALUE = 0 THEN a2.[VALUE] ELSE a1.[VALUE] END AS [VALUE],
CASE WHEN a1.CHECKID = 1 AND a1.VALUE = 0 THEN a2.CHECKID ELSE a1.CHECKID END AS CHECKID
FROM
allData a1
INNER JOIN allData a2 ON a2.MLID = a1.MLID + 1 AND a2.CHECKID = 2
WHERE
a1.CHECKID = 1;
I guess this might get you started on a better query, or even raise some questions about what you actually need, and how these rows are related?
In SQL Server I am creating a view that shows if a record in table CONTACTS has certain tags in a different table TAGS.
This is my query:
SELECT DISTINCT
contacts.ID, contacts.NAME,
IIF(tags.tag = 'A', 1, 0) as A,
IIF(tags.tag = 'B', 1, 0) as B,
IIF(tags.tag = 'C', 1, 0) as C,
IIF(tags.tag = 'D', 1, 0) as D
FROM
contacts
LEFT JOIN
TAGS ON contacts.ID = TAGS.CONTACT_ID
I would like the results like this:
ID NAME A B C D
------------------------------------
1 BOB 1 0 0 1
1 Charlie 1 0 1 0
but I get
ID NAME A B C D
------------------------------------
1 BOB 1 0 0 0
1 BOB 0 0 0 1
1 Charlie 1 0 0 0
1 Charlie 0 0 1 0
Must be something I overlook, but I can't find it.
You need simply use GROUP BY clause + MAX aggreate instead of DISTINCT
SELECT contacts.ID, contacts.NAME
, MAX(IIF(tags.tag = 'A', 1, 0)) as A
, MAX(IIF(tags.tag = 'B', 1, 0)) as B
, MAX(IIF(tags.tag = 'C', 1, 0)) as C
, MAX(IIF(tags.tag = 'D', 1, 0)) as D
FROM contacts LEFT JOIN
TAGS ON contacts.ID = TAGS.CONTACT_ID
group by
contacts.ID, contacts.NAME
As Gordon Linoff says, use of standard SQL case when is more compatible with all the database (postgres, oracle, sql server ...)
IIF(tags.tag = 'A', 1, 0)
is equivalent to
CASE WHEN tags.tag = 'A' THEN 1 ELSE 0 END
Use group by:
SELECT c.ID, c.NAME,
MAX(CASE WHEN t.tag = 'A' THEN 1 ELSE 0 END) as A,
MAX(CASE WHEN t.tag = 'B' THEN 1 ELSE 0 END) as B,
MAX(CASE WHEN t.tag = 'C' THEN 1 ELSE 0 END) as C,
MAX(CASE WHEN t.tag = 'D' THEN 1 ELSE 0 END) as D
FROM contacts c LEFT JOIN
TAGS t
ON c.ID = t.CONTACT_ID
GROUP BY c.ID, c.NAME;
Note changes the query:
Introduced table aliases. These make the query easier to write and to read.
Removed the SELECT DISTINCT, because you really want a GROUP BY.
Changed IIF() to CASE. I see no reason to use a function designed for backward compatibility to MS Access over the SQL standard function.
SELECT contacts.ID, contacts.NAME
, MAX(IIF(tags.tag = 'A', 1, 0)) as A
, MAX(IIF(tags.tag = 'B', 1, 0)) as B
, MAX(IIF(tags.tag = 'C', 1, 0)) as C
, MAX(IIF(tags.tag = 'D', 1, 0) as D
FROM contacts LEFT JOIN
TAGS ON contacts.ID = TAGS.CONTACT_ID
GROUP BY contacts.ID, contacts.NAME
Not sure if the title made sense.
But this what I need, I am bad at sql:
I have table with the following data
ID| Value
------ | ------
1| A
1| B
1| C
1| D
2| A
2| B
2| C
I need O/P as
2 A
2 B
2 C
Using Select id where value in (A,B,C) and Not in (D)
is giving me o/p as
1 A
1 B
1 C
2 A
2 B
2 C
Need to select Id's having A,B,C but not D.
If you want to get rows which has one or more value in A, B, C, but not D:
select *
from your_table
where value in ('A', 'B', 'C')
and id not in (
select id
from your_table
where value = 'D'
);
If you want that all the three values A, B, C must be present for that id and but not D.
select id,
value
from (
select t.*,
count(distinct value) over (partition by id) n
from your_table t
where value in ('A', 'B', 'C')
and id not in (
select id
from your_table
where value = 'D'
)
)
where n = 3;
If you want to get rows having only A, B, C (and all of them present) then use :
select id,
value
from (
select t.*,
count(case
when value not in ('A', 'B', 'C')
then 1
end) over (partition by id) n,
count(distinct case
when value in ('A', 'B', 'C')
then value
end) over (partition by id) n2
from your_table t
)
where n = 0
and n2 = 3;
You can use conditional aggregation in a HAVING clause to filter across rows for each id:
SELECT id
FROM table1
GROUP BY id
HAVING MAX(CASE WHEN value = 'A' THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN value = 'B' THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN value = 'C' THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN value = 'D' THEN 1 ELSE 0 END) = 0
This will show you which id values meet your criteria, and if you need you can put this in a subquery and join it to your table to get all the rows for that id:
SELECT a.*
FROM table1 a
JOIN ( SELECT id
FROM table1
GROUP BY id
HAVING MAX(CASE WHEN value = 'A' THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN value = 'B' THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN value = 'C' THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN value = 'D' THEN 1 ELSE 0 END) = 0
) b
ON a.id = b.id
From your question, I understood that to find the count of Value column where the values are A, B, C but Value not equal to D. Then simply put those 3 value in IN operator. I will retrieve the result set without D.
Query
SELECT COUNT(Value) count, Value
FROM your_table_name
WHERE Value in ('A', 'B', 'C')
GROUP BY Value;
select id, value
from my_table
where value in ('A','B','C')
and id = 2
Have the following Data in the table
Example Table
ID Value
1 a
1 b
1 c
2 a
2 b
2 c
3 a
3 b
I need to retrieve records having ID with only two values a and b.
So i am expecting only the Record with ID 3 .
Can anyone help me with the query
I guess you could do something like
select
ID,
sum(case when value = 'a' then 1
when value = 'b' then 1
else 3 end)
from
table1
group by id
having
sum (case when value = 'a' then 1
when value = 'b' then 1
else 3 end) =2
SQL Fiddle
That will work:
select x.id from
(
select id from mytable where value = 'a'
union all
select id from mytable where value = 'b'
) x
group by x.id
having COUNT(*) = 2
and not exists (select * from mytable t where t.id = x.id and value <> 'a' and value <> 'b')