I have three tables w some records below. I was expecting to return on two distinct Keys with a 'BERRY' in Group field. However, for example the KEYs = 179526189 shows BERRY and COCA instead of just BERRY.
Table A
AGE AGE_IND KEYS
34 (null) 179526189
6 N 179526390
Table B
ID STATUS FK_KEY
16478 (null) 179526189
16478 (null) 179526390
16479 (null) 179526189
16479 (null) 179526390
Table C
FK_ID PRO_CODE DEL_DT
16478 Drug 6/10/2014 12:00:00 AM
16479 Drug (null)
SELECT KEYS,
CASE WHEN (AGE < 18 AND AGE_IND = 'Y') AND (B.STATUS != 'S' or B.STATUS is null) THEN 'APPLE'
WHEN C.PRO_CODE = 'Drug' THEN 'BERRY'
WHEN AGE >= 18 THEN 'COCA'
ELSE 'APPLE' END as Groups,
COUNT(DISTINCT KEYS) AS CT
FROM #tableA A
LEFT OUTER JOIN #tableB B
ON (A.KEYS = B.FK_KEY AND (B.STATUS <>'S' or B.STATUS IS NULL))
LEFT OUTER JOIN #tableC C
ON (B.ID = C.FK_ID AND C.DEL_DT IS NULL)
GROUP BY KEYS,
CASE WHEN (AGE < 18 AND AGE_IND = 'Y') AND (B.STATUS != 'S' or B.STATUS is null) THEN 'APPLE'
WHEN C.PRO_CODE = 'Drug' THEN 'BERRY'
WHEN AGE >= 18 THEN 'COCA'
ELSE 'APPLE' END
running the above query, yields
KEYS Groups CT
179526189 BERRY 1
179526189 COCA 1
179526390 APPLE 1
179526390 BERRY 1
Would you please tell me what is wrong with my CASE expression? so that my expected result yields:
KEYS Groups CT
179526189 BERRY 1
179526390 BERRY 1
You are grouping by GROUPS so you get each one. Choose one! It is not clear how you are choosing 'BERRY', but if you want one row per KEYS, then the idea is to only include that in the GROUP BY:
SELECT KEYS,
MAX(CASE WHEN (AGE < 18 AND AGE_IND = 'Y') AND (B.STATUS != 'S' or B.STATUS is null) THEN 'APPLE'
WHEN C.PRO_CODE = 'FMU' THEN 'BERRY'
WHEN AGE >= 18 THEN 'COCA'
ELSE 'APPLE'
END) as Groups,
COUNT(DISTINCT KEYS) AS CT
FROM #tableA A LEFT OUTER JOIN
#tableB B
ON A.KEYS = B.FK_KEY AND (B.STATUS <>'S' or B.STATUS IS NULL) LEFT OUTER JOIN
#tableC C
ON B.ID = C.FK_ID AND C.DEL_DT IS NULL
GROUP BY KEYS;
Related
I'm trying to find how many MED types have a child ORAL type that do NOT have a child IV type in the following table.
ID
PARENT_ID
TYPE
1
NULL
MED
2
1
ORAL
3
NULL
MED
4
3
ORAL
5
3
IV
6
NULL
MED
7
6
ORAL
8
NULL
MED
9
8
ORAL
12
NULL
MED
13
12
ORAL
14
12
IV
15
12
ORAL
I can find a count of All MED types that have a child ORAL type AND a child IV type with the following.
select count(distinct(a.ID))
from Table1 a
join Table1 b
on a.ID = b.PARENT_ID
join Table1 c
on a.ID = c.PARENT_ID
where a.TYPE = 'MED' and b.TYPE = 'ORAL' and c.TYPE = 'IV'
But I can't figure out how to filter out the MEDs that only have type ORAL and NOT type IV. This is what I tried but it returns nothing. It should return a count of 3 (rows 1, 6, 8).
select count(distinct(a.ID))
from Table1 a
join Table1 b
on a.ID = b.PARENT_ID
where a.TYPE = 'MED' and b.TYPE = 'ORAL'
and not exists (
select a.ID
from Table1 a
join Table1 b
on a.ID = b.PARENT_ID
join Table1 c
on a.ID = c.PARENT_ID
where a.TYPE = 'MED' and b.TYPE = 'ORAL' and c.TYPE = 'IV'
)
If I understand you correctly, then you can solve the problem like this
We take all records by condition and exclude keys where IV is present
SELECT COUNT(*)
FROM table1 t1
JOIN table1 t2
ON t1.id = t2.parent_id
AND t2.utype = 'ORAL'
WHERE t1.utype = 'MED'
AND t1.id NOT IN (SELECT parent_id FROM table1 t3 WHERE t3.utype = 'IV')
First of all, thank you for your time helping me!
I have the following (example) 5 tables.
Table 1
username
1
2
3
4
5
Table 2
Username
Role
1
D
2
O
3
S
4
A
Table 3
Name
Privilege
Option
1
AD
N
2
CC
Y
3
DT
N
4
MS
Y
Table 4
Username
Option1
option2
1
T
T
2
F
T
3
T
F
Table 5
Username
privilege_1
AO
1
E
No
2
I
Yes
3
U
Yes
4
A
No
I'm trying to achieve Output that should be like :
All the users from five tables in one 'username' column
and their corresponding role(from table2),privilege(from table3),option1(from table4),option2(from table4),privilege_1(from table5) into 'Type' column
and if role(from table2) for a user is in (D , O , S) then HP should be 'Yes' for those users, if privilege (from table3 ) is in 'CC', 'MS' for that user then HP is 'Yes', option1,option2(from table4) is 'T' for that user then HP is 'Yes', (Privilege_1 (from table5) is 'U' and AO(from table5) is 'Yes' for that user then HP is 'Yes'
username
type
HP
1
D
Yes
2
O
Yes
3
S
Yes
4
A
No
1
AD
No
2
CC
Yes
3
DT
No
4
MS
Yes
1
T
Yes
2
F
No
3
T
Yes
1
T
Yes
2
T
Yes
3
F
No
1
E
No
2
I
No
3
U
Yes
4
A
No
5
(null)
(null)
The query that I have written is :
select
username,
case
when table2.role is not null then table2.role
when table3.privilege is not null then table3.privilege
when table4.option1 is not null then table4.option1
when table4.option2 is not null then table4.option2
when table5.privilege_1 is not null then table5.privilege_1
end as type
case
when table2.role in ('D','S') then 'Yes'
when table3.privilege in ('CC', 'MS') then 'Yes'
when table4.option1 = 'T' then 'Yes'
when table4.option2 = 'T' then 'Yes'
when table5.privilege_1 in ('U') and table4.AO = 'Yes' then 'Yes'
else 'No'
End as HP
from table1
left join table2
on table1.username = table2.username
left join table3
on table1.username =table3.name
left join table4
on table1.username = table4.username
left join table5
on table1.username = table5.username;
I have worked on above query but I was not able to get the entire data.
When you join multiple tables like that on username, try starting out with select * from .... Notice that all of the table values are in the same row! You can't split them back out into separate rows by using CASE, you need to start out with all of them in separate rows. I think you want to UNION those secondary table rows together.
Example:
select *
from table1
left join (select username, table2.role as type,
case when table2.role in ('D','O','S') then 'Yes' else 'No' as HP
from table2
union
select name as username, privilege as type,
case when table3.privilege in ('CC', 'MS') then 'Yes' else 'No' as HP
from table3
union
select username, option1 as type,
case when table4.option1 = 'T' then 'Yes' else 'No' as HP
from table4
union
select username, option2 as type,
case when table4.option2 = 'T' then 'Yes' else 'No' as HP
from table4
union
select username, privilege_1 as type,
case when table5.privilege_1 in ('U') and table5.AO = 'Yes' then 'Yes' else 'No' as HP
from table5) x
on x.username = table1.username;
Edit: when 5 or 9 does not exist, i need a null value (or another flag)
I have 3 columns. SECTION, STATUS and NAME. Within a SECTION there are a maximum of 10 rows (STATUS 1 to 10). I have to compare the value of NAME for STATUS 5 and 9 within a SECTION. AND then indicate if those 2 NAMES (for STATUS 5 and 9) are the same for each SECTION.
section status name
1 5 a
1 6 a
1 9 b
2 4 c
2 5 d
2 9 d
2 10 d
3 5 e
3 10 e
Desired output
Section equalnames
1 no
2 yes
3 null/flag
select
a.section,
case
when a.name = b.name then 'YES'
when a.name <> b.name then 'NO'
when (a.name is null or b.name is null) then 'NULL' end
from
(select * from <table> where status = 5) a
full join (select * from <table> where status = 9) b
on a.section = b.section
With conditional aggregation:
SELECT section,
MAX(CASE WHEN status = 5 THEN name END) =
MAX(CASE WHEN status = 9 THEN name END) equalnames
FROM tablename
WHERE status IN (5, 9)
GROUP BY section
ORDER BY section
See the demo.
Results:
section | equalnames
------- | ----------
1 | f
2 | t
3 | null
You could try using a left join on same table for 5 and 9
select a.section, a.status s5, a.name n5, b.status b9, b.name n9
, case when a.name = b.name the yes
when a.name is null or b.name is nul the NULL
when a.name <> b.name then no end equalname
from my_table a
left join my_table b a.section = b.section and a.status =5 and b.status=9
A more optimised solution could be with cte and window function:
with cte as (
select section, count(status)over(partition by section,name order by section) count_with_same_name,
count(status)over(partition by section order by section) count_with_different_name
from tname where status in (5,9))
select section,(case when (max(count_with_same_name)=2) then 'Yes' when (max(count_with_different_name)=2) then 'No' else 'null/flag' end)
from cte
group by section
Output:
I think you just want conditional aggregation:
select section,
(case when min(case when status = 5 then name end) =
min(case when status = 9 then name end)
then 'yes'
when count(case when status in (5, 9) then status end) < 2
then 'null/flag'
else 'no'
end)
from t
group by section;
No join is needed and I would not advise one for this problem.
I am trying to devise an SQL statement where I am getting said error in the subject. I understand that there are other topics on this error but have not seen any regarding my specific problem where I am trying to get a value based off multiple rows. I would appreciate any insight. Here are my simplified Tables and SQL statement.
TableA:
member_id
----------
1
2
3
4
TableB:
user_id field_id value
------------------------
1 1 red
2 2 red
1 2 blue
4 1 red
2 1 blue
3 1 blue
Query:
SELECT DISTINCT(member_id)
FROM TableA
WHERE member_id = (SELECT b.user_id
FROM TableB b
INNER JOIN TableB a on a.user_id = b.user_id
WHERE a.field_id = '1' ANd a.value = 'red'
AND b.field_id = '2' ANd b.value = 'blue')
I am trying to select the member_id from table A as the user_id in Table B where in table B the user's field_id(1) = red and the same user's field_id(2) = blue.
Therefore the select statement should return the member_id with id = 1.
Use the query you had for the sub select and just JOIN tableA.
SELECT a.*
FROM TableB b1
INNER JOIN TableB b2 on b1.user_id = b2.user_id
INNER JOIN tableA a ON a.member_id = b1.user_id
WHERE b2.field_id = '1' ANd b2.value = 'red'
AND b1.field_id = '2' ANd b1.value = 'blue'
Grouping by user_id, you could try counting the hits and filter accordingly:
SELECT user_id
FROM tableB
GROUP BY user_id
HAVING SUM(CASE WHEN field_id = 1 AND value = 'red' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN field_id = 2 AND value = 'blue' THEN 1 ELSE 0 END) > 0
And how about another variation:
SELECT *
FROM tableA AS a
WHERE EXISTS (SELECT 1 FROM tableB b where b.user_id = a.member_id AND B.field_id = 1 AND B.value = 'red')
AND EXISTS (SELECT 1 FROM tableB b where b.user_id = a.member_id AND B.field_id = 2 AND B.value = 'blue')
Your inner query is doing an inner join of TableB to itself. This is almost never necessary.
If you want records from tableA where the user_id = member_id, and field_ID = 1 when value = red, or field_id = 2 when value = blue, you'll want something more like this:
SELECT distinct(member_id)
FROM TableA inner join TableB on user_id = member_id
WHERE (field_id = '1' AND value = 'red')
OR (field_id = '2' AND value = 'blue')
If you want only records where they have both, just throw a distinct on your original inner query.
I have such query. It returns ColA and ColB from TableA and UserName from table Users. Then it displays several fields from TableB as additional columns to results. It works but is there any better way than using these multiple LEFT JOINS ?
SELECT a.COlA, a.ColB, u.UserName,
b1.Value,
b2.Value,
b3.Value,
b4.Value,
FROM TableA a JOIN Users u ON a.UserId = u.UserId
LEFT JOIN TableB b1 ON a.EventId = b1.EventId AND b1.Code = 5
LEFT JOIN TableB b2 ON a.EventId = b2.EventId AND b2.Code = 15
LEFT JOIN TableB b3 ON a.EventId = b3.EventId AND b3.Code = 18
LEFT JOIN TableB b4 ON a.EventId = b4.EventId AND b4.Code = 40
WHERE (a.UserId = 3) ORDER BY u.UserName ASC
TableB looks like:
Id | EventId | Code | Value
----------------------------
1 | 1 | 5 | textA
2 | 1 | 15 | textB
3 | 1 | 18 | textC
Sometimes Code is missing but for each event there are no duplicated Codes (so each LEFT JOIN is just another cell in the same result record).
I cannot understand why you want to change something that is working, but here's another way (which does those LEFT joins, but in a different way):
SELECT a.COlA, a.ColB, u.UserName,
( SELECT b.Value FROM TableB b WHERE a.EventId = b.EventId AND b.Code = 5 ),
( SELECT b.Value FROM TableB b WHERE a.EventId = b.EventId AND b.Code = 15 ),
( SELECT b.Value FROM TableB b WHERE a.EventId = b.EventId AND b.Code = 18 ),
( SELECT b.Value FROM TableB b WHERE a.EventId = b.EventId AND b.Code = 40 )
FROM TableA a JOIN Users u ON a.UserId = u.UserId
WHERE (a.UserId = 3)
ORDER BY u.UserName ASC
SELECT
a.COlA, a.ColB, u.UserName
,MAX(CASE WHEN b.Value = 5 THEN b.value ELSE 0 END) AS V5
,MAX(CASE WHEN b.Value = 15 THEN b.value ELSE 0 END) AS V15
,MAX(CASE WHEN b.Value = 18 THEN b.value ELSE 0 END) AS V18
,MAX(CASE WHEN b.Value = 40 THEN b.value ELSE 0 END) AS V45
,COUNT(CASE WHEN b.Value not IN (5,15,18,40) THEN 1 ELSE NULL END) AS CountVOther
FROM TableA a
INNER JOIN Users u ON a.UserId = u.UserId
LEFT JOIN TableB b ON (a.EventId = b.EventId)
WHERE (a.UserId = 3)
GROUP BY a.colA, a.colB, u.Username
ORDER BY u.UserName ASC