I need a Case Statement where I can choose the answers depending on if the Answer column has a NULL value or not.
For example if one of the rows has a NULL in Answer, i would only choose the names showing up that is not Null. And would like it to display like "Clark Kent And Lois Lane".
If there was just one name in the Answer column then i would like it just show "Clark Kent"
QuestionID | EncounterID | Answer |
---|---|---|
1636 | 1234 | Clark Kent |
1637 | 1234 | NULL |
1638 | 1234 | Lois Lane |
CodePudding user response:
Try this Query:
select t.EncounterID,
STUFF((
SELECT (' and ' isnull([Answer],'') ) )
FROM [TableName] t2
where t2.EncounterID=t.EncounterID
FOR XML PATH('')), 1, 4, '')
from [TableName] t
group by t.EncounterID
CodePudding user response:
You can use STRING_AGG
within a CTE
, then RIGHT JOIN
the CTE
to your table
and use a CASE
statement to check for NULL
values, replacing it with the STRING_AGG
result from the CTE
like this:
WITH cte AS (SELECT a.EncounterID,
STRING_AGG(a.Answer, ' and ') AS Concat_Column
FROM sample_table a
GROUP BY a.EncounterID)
SELECT
c.QuestionID,
c.EncounterID,
CASE WHEN c.Answer IS NULL THEN d.Concat_Column
ELSE c.Answer
END AS Answer
FROM cte d
RIGHT JOIN sample_table c ON d.EncounterID = c.EncounterID AND c.Answer IS NULL
Optionally, you can use a subquery to get the same result:
SELECT c.QuestionID,
c.EncounterID,
CASE WHEN c.Answer IS NULL THEN b.Answer
ELSE c.Answer
END AS Answer
FROM sample_table c
LEFT JOIN (SELECT a.EncounterID,
STRING_AGG(a.Answer, ' and ') AS Answer
FROM sample_table a
GROUP BY a.EncounterID) b
ON b.EncounterID = c.EncounterID AND c.Answer IS NULL
Input:
QuestionID | EncounterID | Answer |
---|---|---|
1636 | 1234 | Clark Kent |
1637 | 1234 | Lois Lane |
1638 | 1234 | null |
1639 | 1235 | null |
1640 | 1235 | Lex Luthor |
1641 | 1235 | null |
1642 | 1236 | General Zod |
1643 | 1237 | Perry White |
1644 | 1237 | null |
1645 | 1238 | Jimmy Olsen |
1646 | 1239 | Superman |
1647 | 1239 | Lana Lang |
1648 | 1239 | null |
1649 | 1239 | null |
Output:
QuestionID | EncounterID | Answer |
---|---|---|
1636 | 1234 | Clark Kent |
1637 | 1234 | Lois Lane |
1638 | 1234 | Clark Kent and Lois Lane |
1639 | 1235 | Lex Luthor |
1640 | 1235 | Lex Luthor |
1641 | 1235 | Lex Luthor |
1642 | 1236 | General Zod |
1643 | 1237 | Perry White |
1644 | 1237 | Perry White |
1645 | 1238 | Jimmy Olsen |
1646 | 1239 | Superman |
1647 | 1239 | Lana Lang |
1648 | 1239 | Superman and Lana Lang |
1649 | 1239 | Superman and Lana Lang |
db<>fiddle here.
Also, if you want to remove the duplicate names (which would also remove unique QuestionID
's) you can add the ROW_NUMBER()
window function to the outer SELECT
statement which will assign a sequential integer based on the EncounterID
column and the Answer
column from the STRING_AGG
function. Then, wrap the outer query in parentheses to create another subquery, selecting only values WHERE
row number = 1 to get the distinct Answer
rows.
SELECT d.QuestionID,
d.EncounterID,
d.Answer
FROM (SELECT ROW_NUMBER() OVER (PARTITION BY c.EncounterID,
CASE WHEN c.Answer IS NULL THEN b.Answer
ELSE c.Answer
END ORDER BY c.EncounterID) as rn,
c.QuestionID,
c.EncounterID,
CASE WHEN c.Answer IS NULL THEN b.Answer
ELSE c.Answer
END AS Answer
FROM sample_table c
LEFT JOIN (SELECT a.EncounterID,
STRING_AGG(a.Answer, ' and ') AS Answer
FROM sample_table a
GROUP BY a.EncounterID) b
ON b.EncounterID = c.EncounterID AND c.Answer IS NULL) d
WHERE d.rn = 1
Output:
QuestionID | EncounterID | Answer |
---|---|---|
1636 | 1234 | Clark Kent |
1638 | 1234 | Clark Kent and Lois Lane |
1637 | 1234 | Lois Lane |
1639 | 1235 | Lex Luthor |
1642 | 1236 | General Zod |
1643 | 1237 | Perry White |
1645 | 1238 | Jimmy Olsen |
1647 | 1239 | Lana Lang |
1646 | 1239 | Superman |
1648 | 1239 | Superman and Lana Lang |
db<>fiddle here.