SQL Select for multiple where clause - sql

I am trying to create SQL Select that returns counts of a certain field based on a field.
So, here is what I am trying to do.
Select count(distinct id) as TotalCount, -- this will be the total of id
count(distinct id where type='A') as TotalA, -- this will be total when type='A'
count(distinct id where type='B') as TotalB -- This will be total when type = 'B'
from MyTable
Basically, TotalCount = TotalA + TotalB.
How can I achieve this in SQL Select Statement?
Thanks.

Select count(distinct id) as TotalCount, -- this will be the total of id
count(distinct case type when 'A' then id else NULL end) as TotalA,
count(distinct case type when 'B' then id else NULL end) as TotalB
from MyTable;
Of course TotalCount may or may not be TotalA + TotalB, depending on the actual data.

You can do it like that:
SELECT
count(distinct id) as TotalCount,
sum(CASE WHEN type = 'A' THEN 1 ELSE 0) as TotalA,
sum(CASE WHEN type = 'B' THEN 1 ELSE 0) as TotalB,
FROM
MyTable
Count per type:
SELECT
type,
count(DISTINCT id)
FROM
MyTable
GROUP BY
type

Why not simply UNION the separate queries.
Select 'all' as which, count(distinct id) as Total from mytable
union
select 'a' as which, count(distinct id) where type='A' as Total from mytable
union
select 'b' as which, count(distinct id) where type='B' as Total from mytable

Related

sql transformation - rows to column

i have been trying to solve this one image
my initial idea is like this
select name,
CASE
when count(name) = 1 then get first distinct value
when count(name) = 2 then get first distinct value
else get first distinct value
END as val1,
CASE
when count(name) = 1 then null
when count(name) = 2 then get second distinct value
else get second distinct value
END as val2,
CASE
when count(name) = 1 then null
when count(name) = 2 then null
else get third distinct value
END as val3
into desired_table
from source_table
group by name
is my attempt feasible? if so, how do i access the first, second and third distinct values?
use pivot . Your output table was incorrect. The correct form is available in db<>fiddle.
select name,x as value1,y as value2,z as value3
from
(
select *
from t1
) as SourceTable
pivot
(
max(value) for value in(x,y,z)
) as PivotTable
demo in db<>fiddle
You can use conditional aggregation along with row_number():
select name,
max(case when seqnum = 1 then value end) as value_1,
max(case when seqnum = 2 then value end) as value_2,
max(case when seqnum = 3 then value end) as value_3
into desired_table
from (select s.*,
row_number() over (partition by name order by value) as seqnum
from source_table s
) s
group by name;

SQL: Select within Select as subquery

I've got the following statement:
select
product_name as ShortestLength = (select top 1 product_name, len(fact_name) Value_Length
from table
order by Value_Length, fact_name ASC)
Which returns this output:
shortestlength
PS
I'd like to add this outcome to another select statement:
select
'Product' as Column_Name,
avg(case when product is null then 1.000 else 0 end) * 100 as PctMissing,
count(product) as TotalCount,
count(distinct product) as UniqueCount
from
table
so the result will be:
column_name
pctmissing
totalcount
uniquecount
shortestlength
Product
5.100
181186
15
PS
What should I add to my initial select statement?
You can use conditional aggregation:
select 'Product' as Column_Name,
avg(case when t.product is null then 1.000 else 0 end)*100 as PctMissing,
count(t.product) as TotalCount,
count(distinct t.product) as UniqueCount,
max(case when seqnum = 1 then product_name end) as shortest_length
from (select t.*,
row_number() over (order by len(fact_name), fact_name) as seqnum
from table t
) t
This assumes that the two table references are really the same table.
You can just use first query as subquery in place of a column in your select statement:
select
'Product' as Column_Name,
avg(case when product is null then 1.000 else 0 end)*100 as PctMissing,
count(product) as TotalCount,
count(distinct product) as UniqueCount,
(select top 1 product_name from table order by Value_Length, fact_name ASC) as ShortestLength
from table

Need to get difference between these two as output

REQUIRED QUERY :
select all memberid from query 1 having higher count than query 2
the aim is to display all memberid who were leader/organiser/helper more times than they participate in event
how do i join these two select statement and view the required output
SELECT memberID, COUNT(*) AS cnt
FROM
(
SELECT memberID FROM leader UNION ALL
SELECT memberID FROM organiser UNION ALL
SELECT memberID FROM helper
) t
GROUP BY memberID;
=============
select memberid,count(*) as cnt2
from eventmember group by memberid;
=======
another, "all_in_one" solution
select
memberid,
count(*) as total_cnt,
sum(case when type = 'eventmember' then 1 else 0 end) as eventmember_cnt,
sum(case when type = 'eventmember' then 0 else 1 end) as other_cnt
from
( select memberid, 'leader' as type
from leader union all
select memberid, 'organiser' as type
from organiser union all
select memberid, 'helper' as type
from helper union all
select memberid, 'eventmember' as type
from eventmember
) t
group by
memberid
having
sum(case when type = 'eventmember' then 1 else 0 end)
< sum(case when type = 'eventmember' then 0 else 1 end)
try like below using cte
with cte as
(
SELECT memberID, COUNT(*) AS cnt
FROM
(
SELECT memberID FROM leader UNION ALL
SELECT memberID FROM organiser UNION ALL
SELECT memberID FROM helper
) t
GROUP BY memberID
),cte1 as
(
select memberid,count(*) as cnt2
from eventmember group by memberid
) select cte.memberID,cnt,cnt2 from cte join ct1 on cte.memberID=cte1.memberid

How to get totals for each age category?

proc sql;
create table final as select drink,
count(distinct id) as total_persons,
count(distinct case when age_cat = '20-25' then id end) as tot_20_25,
count(distinct case when age_cat = '25-30' then id end) astot_25_30,
count(distinct case when age_cat = '30-35' then id end) as tot_30_35
from old_table
group by drink
order by total_persons
quit;
This table gives me what i want,but i would like one more row as the totals for all persons and for each category.I can get that single row with correct number if remove from above code the group by steatement.
Is any way to have both cases,by drinks ,and also in same table totals for each category?
You can use union all:
proc sql;
create table final as
select drink,
count(distinct id) as total_persons,
count(distinct case when age_cat = '20-25' then id end) as tot_20_25,
count(distinct case when age_cat = '25-30' then id end) as tot_25_30,
count(distinct case when age_cat = '30-35' then id end) as tot_30_35
from old_table
group by drink
union all
select 'Total',
count(distinct id) as total_persons,
count(distinct case when age_cat = '20-25' then id end) as tot_20_25,
count(distinct case when age_cat = '25-30' then id end) as tot_25_30,
count(distinct case when age_cat = '30-35' then id end) as tot_30_35
from old_table;

Merge two SELECT queries into one

I have two queries where I only need the count of total records but the only difference in the queries is one field value.
Example;
SELECT COUNT(*) AS group_a
FROM tbl
WHERE category = 'value_a'
SELECT COUNT(*) AS group_b
FROM tbl
WHERE category = 'value_b'
How can I get something like this: (pseudo)
SELECT COUNT(*) AS group_a, COUNT(*) AS group_b
FROM tbl
WHERE category IN ('value_a', 'value_b')
But the results are like this
group_a , group_b
56, 101
I was thinking a CASE statement in the query to filter the two but how do I implement it? or is there a better way?
I'm doing a UNION right now but wanted to know if I could return one record with two results
select sum(case when category = 'value_a' then 1 else 0 end) as group_a,
sum(case when category = 'value_b' then 1 else 0 end) as group_b
from tbl
where category in ('value_a', 'value_b')
select sum(case when category = 'value_a' then 1 else 0 end) group_a,
sum(case when category = 'value_b' then 1 else 0 end) group_b
from tbl
SELECT category,COUNT(*) FROM tbl
GROUP BY category;
That expands to more categories. If you want just those categories
SELECT category,COUNT(*) FROM tbl
WHERE category IN ('value_a', 'value_b')
GROUP BY category;
What strange answers for counting. Here's a straightforward COUNT:
SELECT COUNT(category = 'value_a' OR NULL) AS group_a, COUNT(category = 'value_b' OR NULL) AS group_b FROM tbl;
The COUNT aggregate in PostgreSQL allows complex syntax like I've shown. Note that the OR NULL is quite essential as COUNT counts only those rows for which the condition category = '...' OR NULL gives non-NULL answer.
Just for the fun of it:
SELECT *
FROM
(
SELECT category
FROM tbl
) subquery
PIVOT
(
COUNT(category)
FOR category IN ([value_a],[value_b])
) AS piv