Where column "c" is not null for each group in column "a" - give group "a" a value of 1 - sql

Column "C" is a flag indicator. I want to run a query where I can sum column "c" where it is not null. I would like 1 value for each group of column A.
For instance group "Test", would have a total of 1. Group chance has a total of 1. Group "Play" has a total of 0.
I would like a total number as a result. Please view my code below.
A
C
Test
apple
Test
orange
Test
Test
apple
Chance
Chance
apple
Chance
Play
Play
SELECT
sum(case when distinct A and C is not null then 1 else 0 end) as total
FROM table

If you want a flag per a if any c has a value, then you can use:
select a, (case when count(c) > 0 then 1 else 0 end) as has_c
from t
group by a;
You can actually simplify this using the sign() function:
select a, sign(count(c)) as has_c
from t
group by a;
If you want this per row, then use window functions:
select t.*,
(case when count(c) over (partition by a) > 0 then 1 else 0 end)
from t;
Obviously, if you just want to count the non-NULL values, you would use just count(c) without the case expression.

Try this if you just want 1 if exists:
SELECT DISTINCT
a,
1 exsts
FROM
aux
WHERE
c IS NOT NULL
If you want the actual count of occurrences, use:
SELECT
a,
SUM(
CASE
WHEN c IS NOT NULL THEN
1
END
) s
FROM
aux
GROUP BY
a

Related

Counting Booleans for Distinct and Non Distinct ID numbers

I have a simple table that looks like the following PNG file from the following join:
SELECT *
FROM tableA A
JOIN tableB B ON B.Main_SPACE_ID = A.Main_SPACE_ID
Table A contains Guest_ON and User_Controls (last 2 columns) and Table B contains Trigger_ON and DOCX_ON.
Issue:
What I am trying to do is count all the True's for each tableB.Subspace_ID and the DISTINCT trues for tableA.Main_SPACE_ID.
The problem is that subspace_ID from table B lives within the main_space_id from table A and therefore creates a situation where I am double counting.
I only want to count the trues for a distinct Main_space ID
Current Data Model
Desired Output:
From the above screenshot, I am trying to get a count of true values without double counting in the case for tableA_MAIN_SPACE_ID.
As you can see, each row is counted for true values as it relates to the subspace_ID (table B) for totals of 12 and 8 (1 if True, 0 if False) and for tableA, I am only counting distinct values so we only count Trues for a single MainspaceID and avoid recounting them.
If someone can advise on how to get this output from my current data model that would be very helpful!
My attempt as follows double counts trues for the Main space ID column..
SELECT
count(CASE WHEN B.TRIGGER_ON THEN 1 END) as TRIGGER_ON,
count(CASE WHEN B.DOCX_ON THEN 1 END) as DOCX_ON,
count(CASE WHEN A.GUEST_ON THEN 1 END) as SPRINTS,
count(CASE WHEN A.USER_CONTROLS THEN 1 END) as SPRINTS
FROM DataModel
What I am trying to do is count all the True's for each tableB.Subspace_ID and the DISTINCT trues for tableA.Main_SPACE_ID.
You can use conditional aggregation. In Snowflake, you can use the convenient COUNT_IF() for the first two columns. However, for the second two, you need COUNT(DISTINCT) with conditional logic:
SELECT COUNT_IF( B.Trigger_on ) as Trigger_On,
COUNT_IF( B. DOCX_ON ) as DOCX_ON,
COUNT(DISTINCT CASE WHEN A.GUEST_ON THEN A.Main_SPACE_ID END) as GUEST_ON,
COUNT(DISTINCT CASE WHEN A. USER_CONTROLS THEN A.Main_SPACE_ID END) as USER_CONTROLS
FROM tableA A JOIN
tableB B
ON B.Main_SPACE_ID = A.Main_SPACE_ID;
Mabye:
SELECT
COUNT(CASE WHEN B.TRIGGER_ON THEN 1 END) AS TRIGGER_ON,
COUNT(CASE WHEN B.DOCX_ON THEN 1 END) AS DOCX_ON,
(SELECT COUNT(*) FROM (SELECT DISTINCT A.MAIN_SPACE_ID, A.GUEST_ON FROM DataModel WHERE A.GUEST_ON = TRUE) A) AS GUEST_ON
(SELECT COUNT(*) FROM (SELECT DISTINCT A.USER_CONTROLS, A.GUEST_ON FROM DataModel WHERE A.USER_CONTROLS = TRUE) A) AS USER_CONTROLS
FROM DataModel

SQL : Group by and check if all, some or none are set

Lets say I have the following table:
FKEY A B C D E F
'A' 1 0 1 0 1 0
'A' 0 1 1 1 0 0
Now i want to make a group by FKEY but I just want to know if the A-F columns has 1 in one, all or none of the grouped rows.. The resulton the above table would be:
FKEY A B C D E F
'A' S S A S S N
..where S is "some", A is "all" and N is "none".
What would be the best approach to make this query. I could so some nested queries, but isnt there a smarter way?
In my real life data, the 1's and 0's are actually DATETIME and NULL's
You can use case and aggregation:
select fkey,
(case when sum(a) = 0 then 'N'
when sum(a) = count(*) then 'A'
else 'S'
end) as a,
(case when sum(b) = 0 then 'N'
when sum(b) = count(*) then 'A'
else 'S'
end) as b,
. . .
from t
group by fkey;
The above assumes that the values are only 0 and 1. If that is the case, you can actually phrase this as:
(case when max(a) = 0 then 'N'
when min(a) = 1 then 'A'
else 'S'
end) as a,
You mentioned that your 0 and 1 are actually null or non null dates. Here's a modified version of Gordon's query that caters for that:
select fkey,
(case when count(datecol) = 0 then 'all dates are null'
when count(datecol) = count(*) then 'all dates are filled'
else 'some are null, some filled'
end) as a,
...
from t
group by fkey;
COUNT(null) is 0, COUNT('2001-01-01') is 1, COUNT(*) is the row count independent of any variable. Hence, if our count of the dates was 0, all must be null. If the count of the dates was equal to the count of the rows, then all must be filled with some value, otherwise it's a mix

SQL code to count only duplicates where all instances of the duplicate are null

I have a large data set with duplicate reference numbers (reference duplications range from 0 to 37 times). I want to count the number of references only where all instances are null in two columns. So using the table below, the code should return 1 because only Reference Code 3 has all null values, and the duplicates should only be counted once.
I would be grateful for any help.
This involves two steps: (1) isolate all the distinct pairs of values that only have null; (2) count each one once. One way to express this in a query is:
SELECT COUNT(*) FROM
(
SELECT refnum FROM #ref
GROUP BY refnum
HAVING MIN(colA) IS NULL
AND MIN(colB) IS NULL;
) AS x;
Use aggregation to get the codes:
select code
from t
group by code
having max(a) is null and max(b) is null;
If you want the count, use a subquery:
select count(*)
from (select code
from t
group by code
having max(a) is null and max(b) is null
) t;
With conditional aggregation:
select
refcode
from referencecodes
group by refcode
having sum(case when (a is null and b is null) then 0 else 1 end) = 0
The above will return the codes with only null values in a and b.
If you want the number of codes:
select count(r.refcode) from (
select
refcode
from referencecodes
group by refcode
having sum(case when (a is null and b is null) then 0 else 1 end) = 0
) r
Or with EXISTS:
select
count(distinct r.refcode)
from referencecodes r
where not exists (
select 1 from referencecodes
where (refcode = r.refcode) and (a is not null or b is not null)
)
See the demo

How do I check if a certain value exists?

I have a historization table called CUR_VALID. This table looks something like this:
ID CUR_VALID
1 N
1 N
1 Y
2 N
2 Y
3 Y
For every ID there needs to be one Y. If there is no Y or multiple Y there is something wrong. The statment for checking if there are multiple Y I already got. Now I only need to check for every ID if there is one Y existing. Im just not sure how to do that. This is what I have so far. So how do I check if the Value 'Y' exists?
SELECT Count(1) [Number of N]
,MAX(CUR_VALID = 'N')
,[BILL_ID]
,[BILL_MONTH]
,[BILL_SRC_ID]
FROM db.dbo.table
GROUP BY [BILL_ID]
,[BILL_MONTH]
,[BILL_SRC_ID]
Having MAX(CUR_VALID = 'N') > 1
Why are you fiddling with 'N' when you are interested in 'Y'?
Use conditional aggregation to get the count of the value your are interested in.
SELECT
COUNT(*) AS number_of_all,
COUNT(CASE WHEN cur_valid = 'Y' THEN 1 END) AS number_of_y,
COUNT(CASE WHEN cur_valid = 'N' THEN 1 END) AS number_of_n,
bill_id,
bill_month,
bill_src_id,
FROM db.dbo.table
GROUP BY bill_id, bill_month, bill_src_id;
Add a HAVING clause in order to get only valid
HAVING COUNT(CASE WHEN cur_valid = 'Y' THEN 1 END) = 1
or invalid
HAVING COUNT(CASE WHEN cur_valid = 'Y' THEN 1 END) <> 1
bills.
The following query will give you the list of id for which your integrity condition is not met: For every ID there needs to be one Y. If there is no Y or multiple Y there is something wrong.
select T1.id from table T1 where (select count(*) from table T2 where T2.id=T1.id and T2.CUR_VALID='Y')!=1
This query returns both not having at least one 'Y' value and more than one 'Y' value ID's.
First, sum up the Y values and relate to each id, then select not 1 ones from that table.
select * from (
select ID, SUM(case when CUR_VALID = 'Y' then 1 else 0 end) as CNT
from table
group by ID
) b where b.CNT <> 1
DBFiddle
As I understand, you want to get all the id for which your integrity check passes. And integrity check for you means, there is only one row with CUR_VALID value equal to Y in the CUR_VALID table.
This can be achieved by a group by clause:
select id from CUR_VALID
where CUR_VALID.CUR_VALID = 'Y'
group by id
having count(CUR_VALID.CUR_VALID) = 1;

SQL (TSQL) - Select values in a column where another column is not null?

I will keep this simple- I would like to know if there is a good way to select all the values in a column when it never has a null in another column. For example.
A B
----- -----
1 7
2 7
NULL 7
4 9
1 9
2 9
From the above set I would just want 9 from B and not 7 because 7 has a NULL in A. Obviously I could wrap this as a subquery and USE the IN clause etc. but this is already part of a pretty unique set and am looking to keep this efficient.
I should note that for my purposes this would only be a one-way comparison... I would only be returning values in B and examining A.
I imagine there is an easy way to do this that I am missing, but being in the thick of things I don't see it right now.
You can do something like this:
select *
from t
where t.b not in (select b from t where a is null);
If you want only distinct b values, then you can do:
select b
from t
group by b
having sum(case when a is null then 1 else 0 end) = 0;
And, finally, you could use window functions:
select a, b
from (select t.*,
sum(case when a is null then 1 else 0 end) over (partition by b) as NullCnt
from t
) t
where NullCnt = 0;
The query below will only output one column in the final result. The records are grouped by column B and test if the record is null or not. When the record is null, the value for the group will increment each time by 1. The HAVING clause filters only the group which has a value of 0.
SELECT B
FROM TableName
GROUP BY B
HAVING SUM(CASE WHEN A IS NULL THEN 1 ELSE 0 END) = 0
If you want to get all the rows from the records, you can use join.
SELECT a.*
FROM TableName a
INNER JOIN
(
SELECT B
FROM TableName
GROUP BY B
HAVING SUM(CASE WHEN A IS NULL THEN 1 ELSE 0 END) = 0
) b ON a.b = b.b