Using Multiple And's in a Case statement instead of subqueries - sql

I am having a problem using multiple And's in a Case statement.
My Database looks like:
Enrollment Paperless Validated
0 1 0
1 0 1
0 1 0
1 1 1
0 0 0
0 1 0
0 0 0
0 1 0
1 1 1
0 1 0
So my query looks like this:
Select
Count(case when [Enrollment] = 1 and [Paperless] = 1 and [Validated] = 1 then 1 else 0 end) as [Paperless]
,Count(case when [Enrollment] = 1 and [Paperless] = 1 and [Validated] = 1 then 1 else 0 end) as [Online_Only]
,Count(*) as "Total"
FROM [my_table]
Sql Fiddle: http://sqlfiddle.com/#!3/61202/5
As you can see from the sql fiddle the count is always 20 in the case statements when they should be different. Am I just doing something wrong in my case statement or do i have to do them in sub-queries?
Dave

COUNT returns true regardless of the actual value. So use:
SUM(CASE ...)
instead of
COUNT(CASE ...)

Here are two other alternatives:
(1) You can use COUNT(), but drop the ELSE clause. This will result in NULLs rather than 0s, so they won't be counted.
(2) You can also switch to math operations:
SELECT SUM(Enrollment*Paperless*Validated) as <whatever>,
SUM(Enrollment*(1-PaperLess)*Validated) as <something else>
Personally, I often like the multiplication form, because the statement is shorter and I can more often see all the conditions without scrolling.

Related

Select, count, and Group the value in a table that has been joined

I am using SQL Server, and I have two tables: product_assembly and product_testing in the production database
product_assembly table:
serial_number
batch
xx11
1
xx12
1
xx13
2
xx14
2
xx15
1
xx16
3
xx17
3
xx18
3
xx19
2
Table product_testing:
serial_number
batch
xx11
Passed
xx12
Passed
xx13
Passed
xx14
Failed
xx15
Passed
xx16
Passed
xx17
Failed
xx18
Passed
xx19
Passed
How can I get a table like this.
I tried using count, join, and nested SELECT but it doesn't work.
Thank you
Batch
Passed
Failed
1
3
0
2
2
1
3
2
1
We can use conditional aggregation here:
SELECT
pa.batch,
SUM(CASE WHEN pt.batch = 'Passed' THEN 1 ELSE 0 END) AS Passed,
SUM(CASE WHEN pt.batch = 'Failed' THEN 1 ELSE 0 END) AS Failed
FROM product_assembly pa
LEFT JOIN product_testing pt
ON pt.serial_number = pa.serial_number
GROUP BY
pa.batch;

SQL Server Rowcount of column value

I am trying to write a simple SQL code that can get the desired output, from this table -
Original Table :
id | type
123 0
123 1
123 1
345 0
345 0
What I'm trying to get is:
id | zeroCount | oneCount
123 1 2
345 2 0
I tried to group by the id and also type but, both of them gives the same thing!
How to get desired output?
Here is a simple way, assuming the values are only 0 and 1:
select id, sum(1 - type) as zerocount, sum(type) as onecount
from t
group by id;
A more typical approach would use case (or even pivot):
select id, sum(case when type = 0 then 1 else 0 end) as zerocount,
sum(case when type = 1 then 1 else 0 end) as onecount
from t
group by id;
You could get fancy and use a pivot function. But this will work:
Select id,
sum(case when type = 0 then 1 else 0 end) as ZeroCount,
Sum(case when type = 1 then 1 else 0 end) as OneCount
from table
group by id
order by id

One record from multiple records in the table

I have a scenario where ID has three flags.
For example
ID flag1 flag2 flag3
1 0 1 0
2 1 0 0
1 1 0 0
1 0 0 1
2 0 1 0
3 0 1 0
4 1 0 0
Now I want the records having flag2=1 only.. I.e ID=3 has flag2=1 where as ID = 1 and 2 has flag1 and flag3 =1 along with flag2=1. I don't want ID=1 and 2.
I can't make ID unique or primary. I tried with case when statements but it I am somehow missing the basic logic.
We can do it with CTE but I want to repeat this for three different scenarios(Same logic I want to repeat for ID=4 where Flag1=1 only).
You can get the ids with this condition using group by and having:
select id
from table t
group by id
having min(flag2) = max(flag2) and min(flag2) = 1;

return value when count equals variable in sql server

I have a table to update with other table data. For this I created a trigger. Inside trigger, I must check how many active occurrences of each id. If this number of occurrences is same number than a variable value then return 1 (true) otherwise 0 (false).
I get the variable
DECLARE #num_gerencias numeric(2, 0)
SELECT #num_gerencias = (SELECT COUNT(id_gerencia) FROM FR_GERENCIES)
select #num_gerencias
This works ok... returns 5
Then, I make a count of occurrences of the l_activo variable in other table (variable is a bit):
SELECT id_operacio, SUM(CASE WHEN l_activo = 1 THEN 1 ELSE 0 END)
FROM FR_GERENCIES_OPERACIONS o
GROUP BY o.id_operacio
This query also works nice, returns:
2958 5
2959 0
2960 5
2961 3
2962 5
2963 5
2964 2
2965 4
2966 5
2967 5
All perfect... now i must get same list, but if sum equals to #num_gerencias, then put 1 and 0 otherwise.
Expected result table
2958 1
2959 0
2960 1
2961 0
2962 1
2963 1
2964 0
2965 0
2966 1
2967 1
I've tried with CASE
SELECT DISTINCT id_operacio, CASE WHEN
(
SELECT SUM(CASE WHEN l_activo = 1 THEN 1 ELSE 0 END)
FROM FR_GERENCIES_OPERACIONS o
GROUP BY o.id_operacio
) = #num_gerencias THEN 1 ELSE 0 END
but I'm getting error:
Mens . 512 , Level 16 , State 1, Line 6
The subquery returned more than one value , which is not correct when it goes below = , ! = , <, < = ,>, > = Or when used as an expression .
I also tried with an IF (i guess this option is totally wrong for this case... but I've tried)
SELECT DISTINCT id_operacio,
IF #num_gerencias = (SELECT SUM(CASE WHEN l_activo = 1 THEN 1 ELSE 0 END)
FROM FR_GERENCIES_OPERACIONS o
GROUP BY o.id_operacio)
1
ELSE 0
FROM FR_GERENCIES_OPERACIONS
But I have syntax errors...
Any idea how can i reach expected result table?
You were nearly there, however your grouping and selection must occur outside of your case statement:
SELECT DISTINCT
id_operacio
,CASE
WHEN SUM(CAST(l_activo AS INTEGER)) = #num_gerencias THEN 1
ELSE 0
END
FROM FR_GERENCIES_OPERACIONS o
GROUP BY o.id_operacio

SQL get all IDs where Sub-IDs are exactly specified without getting other IDs where some Sub-ID's are not present

Sorry for that title, I don't know how to describe my problem in one sentence.
I have Table like this:
event | thema
-------------
1 1
1 2
2 1
2 2
2 3
3 1
3 2
3 3
3 4
4 1
4 2
4 3
What I want are the event IDs where the thema is exaclty 1, 2 and 3, not the event ID where it is only 1 and 2 or 1,2,3 and 4.
SELECT event WHERE thema=1 OR thema=2 OR thema=3
returns them all
SELECT event WHERE thema=1 AND thema=2 AND thema=3
returns nothing.
I think this should be absolutely simple, but stack is overflown...
Thanks for some help!
Group by the event and take only those having at least one thema 1 and 2 and 3 and not any other
SELECT event
from your_table
group by event
having sum(case when thema = 1 then 1 else 0 end) > 0
and sum(case when thema = 2 then 1 else 0 end) > 0
and sum(case when thema = 3 then 1 else 0 end) > 0
and sum(case when thema not in (1,2,3) then 1 else 0 end) = 0
This type of query is a "set-within-sets" query (your are looking for sets of "thema" for each event). The most general approach is aggregation using a having clause. This might be the shortest way to write the query using standard SQL:
select event
from table t
group by event
having count(distinct (case when thema in (1, 2, 3) then thema end)) = 3;
or,
first create table #themas (depending on vendor, make this a temp table or a simple table-valued variable) that contains user-specified list of thema values, then
Select event from your_table y
Where not exists
(Select * From #Themas t
where Not Exists
(Select * From your_table
where event = y.event
and thema = t.thema))
and not exists (Select * From your_table
where event = t.event
and thema not in
(Select thema From #Themas ))