This question already has answers here:
SQL Case Expression Syntax?
(8 answers)
Closed 7 years ago.
SQL knowledge Beginner
I have a below table: ScoreTable
Name Score Reason Subject
a1 0 NULL NULL
a2 -1 NULL NULL
a3 -3 fail Maths
a4 -3 fail History
a3 0 NULL NULL
I want to write a query which will look some thing like below
Select DISTINCT Name, Result,
(If Result = -3
then Concat(Reason,' ',Subject))As FailedIn)
From ScoreTable
Expected Output:
Name Score FailedIn
a1 0 0
a2 -1 0
a3 -3 fail Maths
a4 -3 fail History
You probably don't want to put "0" and a string in the same column. It is better to use NULL. So:
Select Name, Result,
(case when Result = -3 then Reason + ' ' + Subject
end) as FailedIn
It is unclear why the last row disappears, but perhaps you want something like:
Select Name, min(Result),
(case when min(Result) = -3 then max(Reason + ' ' + Subject)
end) as FailedIn
from table t
group by name
Try using CASE..WHEN..THEN like below and use minimum result score :
SELECT Name, MIN(Result)
CASE WHEN Result = -3
THEN Reason +' '+Subject
ELSE Result
END As FailedIn
FROM mytable
GROUP BY Name, Result
Try this
SELECT NAME, SCORE,
CASE WHEN SCORE = -3 THEN CONCAT(REASON, ' ' ,SUBJECT )
ELSE '0'
END as FAILEDIN FROM ScoreTable
Related
I have table below as
ID | Blood_Type | Size
B2 A 100
B2 B 200
C2 C 102
C2 O 88
G4 I 44
G4 A 100
How can I query my table above to get average of only my IDs that have at least have one row with blood type of A
Expected output:
ID | Avg_Size
B2 150
G4 72
Thanks!
Tim's answer is good, a simpler albeit perhaps not how you would want to do it, other way, is doing HAVING in long form
SELECT id,
avg_size
FROM (
SELECT id,
AVG(size) AS avg_size,
SUM(IFF(blood_type = 'A', 1, 0)) AS a_count
FROM table
GROUP BY id
)
WHERE a_count > 1;
so you can ether use SUM or COUNT, they both ignore nulls, which is the implicit result of Tim's CASE WHEN Blood_Type = 'A' THEN 1 END is the same as
CASE
WHEN Blood_Type = 'A' THEN 1
ELSE NULL
END
if you use SUM it can handle null's or zeros thus the IFF can be used, which I like as it's smaller and more explicit about what is happening.
thus Tim's answer can be swapped to a SUM(IFF
like:
SELECT
id,
AVG(size) AS avg_size
FROM table
GROUP BY id
HAVING SUM(IFF(Blood_Type = 'A',1, 0) > 0;
You may try aggregation here with an assertion in the HAVING clause:
SELECT ID, AVG(Size) AS Avg_Size
FROM yourTable
GROUP BY ID
HAVING COUNT(CASE WHEN Blood_Type = 'A' THEN 1 END) > 0;
I have the following table
ident
name
count
A1
X
1
A1
Y
2
A1
X
6
A2
X
2
A2
Z
3
What i need is a new table which should look like:
ident
X
Y
Z
A1
7
2
0
A2
2
0
3
so it should give me for every distinct id a sum of all the existing names.
But the columns with are build out of the names should be build automaticly.
i have try
SELECT
ident ,
MAX(CASE WHEN (name = 'X') THEN 1 ELSE NULL END) AS X
FROM
mytable
GROUP BY ident
ORDER BY ident
but with this code i have to make the columns and just can set the sum to 0 or 1.
Thx
Use conditional aggregation, which in Postgres looks like this:
select ident,
sum(count) filter (where name = 'X') as x_sum,
sum(count) filter (where name = 'Y') as y_sum,
sum(count) filter (where name = 'Z') as z_sum
from mytable
group by ident;
The FILTER clause is Standard SQL, but Postgres is one of the few databases that actually supports it. You can, of course, do the same thing with CASE expressions, but FILTER gives the optimizer more hints that can help performance (and many people find it cleaner).
you are looking for sum of count:
SELECT
ident ,
SUM(CASE WHEN (name = 'X') THEN count ELSE NULL END) AS X,
SUM(CASE WHEN (name = 'Y') THEN count ELSE NULL END) AS Y,
SUM(CASE WHEN (name = 'Z') THEN count ELSE NULL END) AS Z
FROM
mytable
GROUP BY ident
ORDER BY ident
I have to check certain rows from table and check if-else condition for each rows
TABLE: report
COLUMNS :
sl.no, count, total_count, calls
Sample Data:
sl.no count total_count calls
----------- ----------- ----------- -----------
1 2 6 4
2 2 7 5
3 4 9 3
Here i have to check if condition
if total_count > 6
select 'Y
else
select 'N'
I get correct answer for single row. If there is multiple row it can't check all, it check only last row of my table.
Use CASE expression
SELECT
*,
CASE WHEN total_count > 6 THEN 'Yes' ELSE 'N' END
FROM report
You must use CASE.It work like if-else in t-SQL. MSDN
For example:
SELECT [num],[count], [total_count], [calls], CASE WHEN [total_count] > 6 THEN 'Y' ELSE 'N' END FROM t
You could use CASE. You can read documentation.
SELECT *,
CASE WHEN total_count > 6 THEN 'Y' ELSE ' N' END
FROM Report
The SQL version of "inline if" is CASE:
SELECT
*,
CASE WHEN total_count > 6 THEN 'Y'
ELSE 'N'
END AS IsTotalCountGreaterThanSix
FROM YourTable;
Folks,
I have researched this question first and came up with nothing for my specific issue, I found SUM/CASE which is neat but not exactly what I need. Here is my situation:
I have been asked to report back the total number of people who meet 5 out of 8 conditions.
I am having trouble coming up with the best way of doing this. It must be something to do with having a counter for each condition and then adding the counter at the end and returning the count of people who met 5 of the 8 conditions (call them condition a - h)
So can you do a count of a count?
Something like
if exists (code for condition A) 1 ELSE 0
if exists (code for condition B) 1 ELSE 0
etc
sum(count)
Thank you
Since the conditions are spread across rows, you can do this by combining MAX() and a CASE statement in a HAVING clause:
SELECT person_ID
FROM YourTable
GROUP BY Person_ID
HAVING MAX(CASE WHEN ConditionA THEN 1 END)
+ MAX(CASE WHEN ConditionB THEN 1 END)
+ MAX(CASE WHEN ConditionC THEN 1 END)
+ MAX(CASE WHEN ConditionD THEN 1 END)
+ MAX(CASE WHEN ConditionE THEN 1 END)
+ MAX(CASE WHEN ConditionF THEN 1 END)
+ MAX(CASE WHEN ConditionG THEN 1 END)
+ MAX(CASE WHEN ConditionH THEN 1 END)
>= 5
How about:
WHERE CASE WHEN (Code for condition A) then 1 else 0 end +
CASE WHEN (Code for condition B) then 1 else 0 end +
CASE WHEN (Code for condition C) then 1 else 0 end +
...
= 5
User defined function to the rescue
SELECT * FROM view_people_with_conditions_count WHERE conditions_count BETWEEN 5 AND 8
CREATE VIEW view_people_with_conditions_count
AS
SELECT *, dbo.GetCondtionsCount(id) as conditions_count FROM peoples_table
CREATE function GetCondtionsCount(#id int)
RETURNS int
AS
BEGIN
DECLARE #counter int
' implement your conditions here
IF (condtion1) SET #counter = #counter + 1
IF (condtion2) SET #counter = #counter + 1
IF (condtion3) SET #counter = #counter + 1
RETURN #counter
END
I ended up completing this by using a WITH statement
something like this:
WITH
(
Select statement for first condition AS blah
Select statement for second condition AS blah
Select statement for third condition AS blah
Select statement for fourth condition AS blah
Select statement for fifth condition AS blah
Select statement for sixth condition AS blah
Select statement for seventh condition AS blah
Select statement for eighth condition AS blah
)
select
CASE WHEN (8 cases based on the 8 selects above
I just put the results in a spreadsheet and did all the math in Excel
It is really hard to find a good title for this.
Here is the question: I have a SELECT query GROUP BY a field which returns me up to three values (1,2,3). These values are representing the positions of '1' in a binary number.
In other words:
Query Output | Reult
0,1,2 | 7 (111)
1,2 | 6 (110)
3 | 1 (001)
- | 0 (000)
Ok, I know it is easy. But there are two constraints. First, I want a query not a function/store procedure. Second, the result should be a string (like '010') not the number.
I found the solution for integer value, but not the string (varchar)
SELECT COALESCE(sum(power(2, field)), 0) AS test FROM (
SELECT field FROM myTable GROUP BY field) a
I am using SQL server 2008, just in case.
I also have this solution, but this one cannot be extended to bigger number of outputs:
SELECT output =
CASE TEST
WHEN 0 THEN '000'
WHEN 1 THEN '001'
WHEN 2 THEN '010'
WHEN 3 THEN '011'
WHEN 4 THEN '100'
WHEN 5 THEN '101'
WHEN 6 THEN '110'
WHEN 7 THEN '111'
END
FROM(
select COALESCE(sum(power(2, 3 - field)), 0) as test from (
select field from myTable group by field) a) b
You can use binary and and string concatenation:
select (case when test&4 > 0 then '1' else '0' end) +
(case when test&2 > 0 then '1' else '0' end) +
(case when test&1 > 0 then '1' else '0' end)
from (select 6 as test) t;
If you are allergic to case statements, you could do this:
select CHAR(ascii(0) + (test&4)/4) +
CHAR(ascii(0) + (test&2)/2) +
CHAR(ascii(0) + (test&1)/1)
from (select 6 as test) t