SQL Server counting unrelated conditions - sql

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

Related

Return Parameter If in Child Table Meet Some Condition

I have table like this
Parent table
id, column1, etc
- - -
- - -
Detail
id, parent_id, column1, actual_finish (value is true/false)
- - - -
- - - -
I want to check if all column actual_finish have value true, then return 1 (I think this will be return parameter), else return 0.
For example
parent
id column1 etc,
------------------
1 value1 a
Detail
id, parent_id, column1, actual_finish (value is true/false)
------------------------------------------------------------
1 1 a true
2 1 b false
This will return 0, because second row actual finish value is false, but if second row column actual_finish updated to true, then return 1
I want to create a stored procedure that returns 0 or 1 based on column actual_finish in the detail table.
Can someone help me?
try using,
select min(case when actual_finish='true' then 1 else 0 end) from tab_Detail where parent_id=1;
SP, something like..
create procedure getStatusById
(#id int)
as
begin
declare #res as int=0
set #res=(select min(case when actual_finish='true' then 1 else 0 end) from tab_Detail
where parent_id=#id);
return #res
print(#res)
end
Fiddle
Query you could use is
Select returnvalue= case when totalCount=trueCount then 1 else 0 end
from
(select
trueCount=count (case when actual_finish ='true' then 1 else 0 end),
totalCount = count(1)
from
parent p left join detail d
on p.id=d.parent_id
group by p.id
)T
This is assuming that you return false if there is no row in detail table for parent id
I think requirement is,even one row exists where actual_fnish is false then return 0.
declare #res as int=1
If exists(select 1 from dbo.tbldetail where actual_finish='false')
set #res=0
actual_finish should be BIT data type (0 or 1)
I would recommend using exists. To handle multiple rows in parents:
select p.*,
(case when exists (select 1
from details d
where d.parent_id = p.id and
d.actual_finish = 'false'
)
then 0 else 1
end) as flag
from parents p;

How to provide dynamic usage of select query in SQL Server 2008 based on a variable value

I have a table myTable with these columns and sample data:
Id Name Period0Status Period1Status Period2Status
-------------------------------------------------------
1 Mark 1 2 3
2 John 2 3 3
3 Brad 1 1 1
4 John 3 3 3
5 Mark 1 3 2
etc...
What I want is to use those data but the column names should be taken according to a SQL variable. What I need is something like that:
declare #0_period varchar(50) = 'Period_0'
declare #1_period varchar(50) = 'Period_1'
declare #2_period varchar(50) = 'Period_2'
declare #counter = 0;
while #counter < 3
begin
insert into #Results(Period, JohnVolume, MarkVolume, JoshVolume)
select
'#' + #counter + '_period',
sum(case when(name = 'John' and (Period+#counter+Status = 3) then 1 else 0)),
sum(case when(name = 'Mark' and (Period+#counter+Status = 3) then 1 else 0)),
sum(case when(name = 'Brad' and (Period+#counter+Status = 3) then 1 else 0))
from
myTable
set #counter = #counter + 1
end
I could not find the correct syntax to provide the dynamic query here. Any help would be appreciated. SQL Server 2008 is used.
Output table I want to produce be like:
Period JohnVolume MarkVolume BradVolume
Period_0 1 0 0
Period_1 2 1 0
Period_2 2 1 0
It should basically counts the amount of 3s for each (John,Mark and Brad) for each period. I gotta find out how to correct the syntax for the parts that #counter is used inside the select query.
Here's an example of how you could do this, with a cross apply to derive the values for each period and a count(case...) for the end values:
SELECT period
, COUNT(CASE WHEN Name = 'John' AND val = 3 THEN 1 END) [JohnVolume]
, COUNT(CASE WHEN Name = 'Mark' AND val = 3 THEN 1 END) [MarkVolume]
, COUNT(CASE WHEN Name = 'Brad' AND val = 3 THEN 1 END) [BradVolume]
FROM myTable
CROSS APPLY (VALUES ('Period_0', Period0Status), ('Period_1', Period1Status), ('Period_2', Period2Status)) unp(period, val)
GROUP BY period
The cross apply works as an unpivot to get each period status and the values within them, and the conditional case statements work as a pivot.
Alternatively, you could use an actual UNPIVOT/PIVOT if you want. An example would be:
SELECT Period, John JohnVolume, Mark MarkVolume, Brad BradVolume
FROM (
SELECT *
FROM myTable
UNPIVOT (val FOR period IN (Period0Status, Period1Status, Period2Status)) U
WHERE val = 3) T
PIVOT (COUNT(val) FOR Name IN ([John], [Mark], [Brad])) P

Even or odd in SQL

This is table structure
id
1
2
3
4
5
6
I need result like this
id even odd
1 0 1
2 1 0
3 0 1
4 1 0
5 0 1
6 1 0
I tried
select id %2=0 then 1 else 0 end or id%2 <>0 then 1 else 0 odd
from table
How about
select
id,
~id & 1,
id & 1
from t
Take a look at the CASE keyword. It works very similarly to what you're trying to do in your SELECT statement. In addition, if you want to select multiple columns, separate them with a comma. The OR keyword is used for combining logical conditions in your query, not for specifying multiple columns.
An example of how you could use CASE in your query would be as follows:
SELECT id,
CASE WHEN id %2=0 THEN 1 ELSE 0 END AS Even,
[column2]
FROM [TableName]
The table structure is just Id?
you could try this!
select *,
case when id %2=0 then 1 else 0 end as even,
case when id %2 <>0 then 1 else 0 end as odd
from table
You have the right idea, but your syntax is a bit off. I'd use a CASE statement to create the even column, and then a calculate odd accordingly:
SELECT id, even, ABS(even - 1) AS odd
FROM (SELECT id, CASE WHEN id % 2 = 0 THEN 1 ELSE 0 END AS even
FROM my_table)

SQL - Find the binary representation from the place of '1's

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

Check any 4 out 10 conditions are satisfied in SQL

I apologize for asking a very vague question but here it is.
I have to write a SQL query in SQL Server as follows.
I have a table say tblA having 10 columns from col1, col2,.....col10.
Each column is not null and definitely holds some value and all of type int.
The query should be to select all such records in which at least 4 columns are matching with given filter criteria, where the filter criteria has values for all 10 columns.
I googled dint get a clue. It needs to be done in SQL server and single query.
Please suggest.
Thanks in advance.
SELECT *
FROM
yourtable
WHERE
case col1 when #value1 then 1 else 0 end +
case col2 when #value2 then 1 else 0 end +
...
case col10 when #value10 then 1 else 0 end
>=4
You can use CASE expressions to determine if four or more columns match:
SELECT *
FROM YourTable
WHERE CASE WHEN Col1 = Filter1 THEN 1 ELSE 0 END +
CASE WHEN Col2 = Filter2 THEN 1 ELSE 0 END +
....
CASE WHEN Col10 = Filter10 THEN 1 ELSE 0 END >= 4
You can do something like this:
select *
from (select t.*,
(case when col1 <whatever> then 1 else 0 end) as col01_matches,
(case when col2 <whatever> then 1 else 0 end) as col02_matches,
. . .
from t
) t
where (col1_matches + col2_matches + col3_matches . . .) >= 4
This creates a separate indicator variable for each match. You could also do the sum in the subquery, in a single variable. I would prefer to have each match separately, just in case the logic gets more complicated or I want to see what matches.