How to get totals for each age category? - sql

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;

Related

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

Why can't I order by after doing a concat with a % sign

Select category,
concat(count(category) * 100/ (select count(*) from table3),'%') as category_percentage_males
from table3
where gender in ('m')
group by category
order by category_percentage_males desc
For some reason the order by doesn't return desc once I concat. Without the concat the order by works fine. Any reason as to why this is happening?
This is your query:
Select category, concat(count(category) * 100/ (select count(*) from table3),'%') as category_percentage_males
from table3 where gender in ('m')
group by category
order by category_percentage_males desc;
I would strongly suggest that you require it as:
Select category,
concat(avg(case when gender = 'm' then 100.0 else 0 end), '%') as category_percentage_males
group by category
order by avg(case when gender = 'm' then 100.0 else 0 end) desc;

aggregation functions with different where condition sentence

I have SQL query give table of 6 columns from
mytable:
TotalNumberOfRecords
TotalDurationOfCalls
AvgdurationPer
TotalCallednumbers
TotalCallednumbers
Ratiocalledtoallcalls
these columns resulted of aggregation functions. but each one have different where condition sentences in order to select from table.
MY Query like this:
select ID,
count(*) as TotalNumberOfRecords,
sum (isnull(cast(duration as int),0)) {where condition1} as TotalDurationOfCalls ,
AVG(isnull(cast(duration as int),0)){where condition2} as AvgdurationPer,
count(distinct IDS) {where condition3} as TotalCallednumbers ,
count(distinct CGI) {where condition4} as TotalOfLocations,
cast(count(distinct IDS) as float)/cast(count(*) as float) {where condition5} as Ratiocalledtoallcalls
from Mytable
group by ID
Now, my problem is, how can I execute this query in one query to get one table?
You want conditional aggregation. You do this by making a case expression the argument to an aggregation function:
select ID, count(*) as TotalNumberOfRecords,
sum(case when condition1 then cast(duration as int) else 0 end) as TotalDurationOfCalls ,
avg(case when condition2 then cast(duration as int) else 0 end) as AvgdurationPer,
count(distinct case when condition3 then IDS end) as TotalCallednumbers,
count(distinct case when condition4 then CGI end) as TotalOfLocations,
cast(distinct count(case when condition5 then IDS end) as float)/cast(count(*) as float) as Ratiocalledtoallcalls
from Mytable
group by ID

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

SQL Select for multiple where clause

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