SQL query several columns about the same field but diferent codes - sql

How can I create a query that has multiple counter columns for the same field?
I have a field called card_status that can have 7 different values.
I wanted to create a query that would display total values on the same row and not on 7 different rows.

SELECT SUM(CASE WHEN card_status = 1 THEN 1 ELSE 0 END) as Count_of_1,
SUM(CASE WHEN card_status = 2 THEN 1 ELSE 0 END) as Count_of_2,
...
SUM(CASE WHEN card_status = 7 THEN 1 ELSE 0 END) as Count_of_7
FROM your_table;

You could use a conditional count
For example:
SELECT col1, col2
, COUNT(CASE WHEN card_status = 'revoked' THEN card_status END) AS TotalRevoked
, COUNT(CASE WHEN card_status = 'requested' THEN card_status END) AS TotalRequested
, COUNT(CASE WHEN card_status = 'lost' THEN card_status END) AS TotalLost
-- add more
, COUNT(*) AS Total
FROM YourTable t
GROUP BY col1, col2
ORDER BY col1, col2
This works on the principle that counting a column or expression doesn't count the NULL's

Related

Group by several columns with count on another column SQL Server

I'm using SQL SERVER 2012 and I'm struggling with this SQL statement. Basically I have this table
table
I want to group by Date, and Username, with a count on the status column, like below :
query result
How can I achieve this?
You can use an aggredated query with a few conditional SUMs.
SELECT
LastUpdate,
UpdatedBy as User,
SUM(CASE WHEN Status = 'A' THEN 1 ELSE 0 END) as A
SUM(CASE WHEN Status = 'C' THEN 1 ELSE 0 END) as C
SUM(CASE WHEN Status = 'D' THEN 1 ELSE 0 END) as D
SUM(CASE WHEN Status = 'Z' THEN 1 ELSE 0 END) as Z
SUM(CASE WHEN Status = 'X' THEN 1 ELSE 0 END) as X
FROM table
GROUP BY LastUpdate, UpdatedBy
ORDER BY LastUpdate, UpdatedBy
You can try using conditional aggregation
select LastUpdate,UpdatedBy,
count(case when Status='A' then UpdatedBy end) as 'A',
count(case when Status='C' then UpdatedBy end) as 'C',
count(case when Status='D' then UpdatedBy end) as 'D',
count(case when Status='Z' then UpdatedBy end) as 'Z',
count(case when Status='X' then UpdatedBy end) as 'X'
from tablename
group by LastUpdate,UpdatedBy
Ok I figured it out with help from the guys answers
SELECT
CAST(LastUpdate as DATE),
UserName,
SUM(CASE WHEN Status = 1 THEN 1 ELSE 0 END) as [Status_1],
SUM(CASE WHEN Status = 2 THEN 1 ELSE 0 END) as [Status_2],
SUM(CASE WHEN Status = 3 THEN 1 ELSE 0 END) as [Status_3]
FROM Table
WHERE LastUpdate BETWEEN '2018-11-30 10:013:44.080' AND '2018-12-30 10:013:44.080'
GROUP BY CAST(LastUpdate as DATE), UserName
ORDER BY CAST(LastUpdate as DATE)
This is a sample query where I'm looking for records between two dates. The problem I was having was in part due to filtering on datetime rather than date. The lastupdate column is a datetime so by casting to date it solved the issue

SQL sum of two conditional aggregation

So yesterday I learned about conditional aggregation. I'm fairly new to SQL.
Here is my query:
select
Year_CW,
sum(case when col = 0 then 1 else 0 end) as "Total_sampled(Checked)",
sum(case when col = 1 then 1 else 0 end) as "Total_unsampled(Not_Checked)",
sum(case when col = 0 AND col2 = 'accepted' then 1 else 0 end) as "Accepted",
sum(case when col = 0 AND col2 = 'accepted with comments' then 1 else 0 end) as "Accepted with comments",
sum(case when col = 0 AND col2 = 'request for rework' then 1 else 0 end) as "Request for rework",
sum(case when col = 0 AND col2 = 'rejected' then 1 else 0 end) as "Rejected",
sum(case when col = 0 Or col = 1 then 1 else 0 end) as "Total_DS"
from
(select
Year_CW, SAMPLED as col, APPROVAL as col2
from
View_TEST tv) tv
group by
Year_CW
order by
Year_CW desc
I'm basically just calculating some KPIs grouped by week.
Look at the row for "Total_DS". It is essentially the sum of the first two sums, "Total_sampled(Checked)" and "Total_unsampled(Not_Checked)".
Is there a way that I can add the two columns from the first two sums to get the third one instead of trying to get the data all over again? I feel performance wise this would be terrible practice. It doesn't matter for this database but I don't want to learn bad code practice from the start.
Thanks for helping.
You probably won't see a significant performance hit from what you're doing now as you already have all the data available, you're just repeating the case evaluation.
But you can't refer to the column aliases for the first two columns within the same level of query.
If you can't do a simple count as #Zeki suggested because you aren't sure if there might be values other than zero and one (though this looks rather like a binary true/false equivalent, so there may well be a check constraint limiting you to those values), or if you're just more interested in a more general case, you can use an inline view as #jarhl suggested:
select Year_CW,
"Total_sampled(Checked)",
"Total_unsampled(Not_Checked)",
"Accepted",
"Accepted with comments",
"Request for rework",
"Rejected",
"Total_sampled(Checked)" + "Total_unsampled(Not_Checked)" as "Total_DS"
from (
select Year_CW,
sum(case when col = 0 then 1 else 0 end) as "Total_sampled(Checked)",
sum(case when col = 1 then 1 else 0 end) as "Total_unsampled(Not_Checked)",
sum(case when col = 0 AND col2 = 'accepted' then 1 else 0 end) as "Accepted",
sum(case when col = 0 AND col2 = 'accepted with comments' then 1 else 0 end)
as "Accepted with comments",
sum(case when col = 0 AND col2 = 'request for rework' then 1 else 0 end)
as "Request for rework",
sum(case when col = 0 AND col2 = 'rejected' then 1 else 0 end) as "Rejected"
from (
select Year_CW, SAMPLED as col, APPROVAL as col2
from View_TEST tv
) tv
group by Year_CW
)
order by Year_CW desc;
The inner query gets the data and calculates the conditional aggregate values. The outer query just gets those values from the inner query, and also adds the Total_DS column to the result set by adding together the rwo values from the inner query.
You should generally avoid quoted identifiers, and if you really need them in your result set you should apply them at the last possible moment - so use unquoted identifiers in the inner query, and give them qupted aliases in the outer query. And personally if the point of a query is to count things, I prefer to use a conditional count over a conditional sum. I'm also not sure why you already have a subquery against your view, which just changes the column names and makes the main query slightly more obscure. So I might do this as:
select year_cw,
total_sampled_checked as "Total_sampled(Checked)",
total_unsampled_not_checked as "Total_unsampled(Not_Checked)",
accepted as "Accepted",
accepted_with_comments as "Accepted with comments",
request_for_rework as "Request for rework",
rejected as "Rejected",
total_sampled_checked + total_unsampled_not_checked as "Total_DS"
from (
select year_cw,
count(case when sampled = 0 then 1 end) as total_sampled_checked,
count(case when sampled = 1 then 1 end) as total_unsampled_not_checked,
count(case when sampled = 0 and approval = 'accepted' then 1 end) as accepted,
count(case when sampled = 0 and approval = 'accepted with comments' then 1 end)
as accepted_with_comments,
count(case when sampled = 0 and approval = 'request for rework' then 1 end)
as request_for_rework,
count(case when sampled = 0 and approval = 'rejected' then 1 end) as rejected
from view_test
group by year_cw
)
order by year_cw desc;
Note that in the case expression, then 1 can be then <anything that isn't null>, so you could do then sampled or whatever. I've left out the implicit else null. As count() ignores nulls, all the case expression has to do is evaluate to any not-null value for the rows you want to include in the count.
You can try below
select Year_CW,
sum(case when col = 0 then 1 else 0 end) as "Total_sampled(Checked)",
sum(case when col = 1 then 1 else 0 end) as "Total_unsampled(Not_Checked)",
sum(case when col = 0 AND col2 = 'accepted' then 1 else 0 end) as "Accepted",
sum(case when col = 0 AND col2 = 'accepted with comments' then 1 else 0 end) as "Accepted with comments",
sum(case when col = 0 AND col2 = 'request for rework' then 1 else 0 end) as "Request for rework",
sum(case when col = 0 AND col2 = 'rejected' then 1 else 0 end) as "Rejected",
sum(sum(case when col = 0 then 1 else 0 end) = 0 Or sum(case when col = 1 then 1 else 0 end) = 1 then 1 else 0 end) as "Total_DS"
from (select Year_CW, SAMPLED as col, APPROVAL as col2
from View_TEST tv
) tv
group by Year_CW
order by Year_CW desc

field to identify a group has a certain value or not in SQL Server 2012

I have a table, Table 1 with 2 columns.
My result table should look like
.
Representing the presence of a certain value in the group. The table1 is very huge, I don't want to use any cursor or loops. Please suggest me a better way to do it in SQL
Use conditional logic. Here is one approach:
select column1,
(case when sum(case when column2 = 'C' then 1 else 0 end) > 0
then 1
end) as has_c,
(case when sum(case when column2 = 'C' then 1 else 0 end) = 0
then 1
end) as does_not_have_c,
from table1 t1
group by column1;
Or more simply as:
select column1,
max(case when column2 = 'C' then 1 end) as has_c,
min(case when column2 = 'C' then 0 else 1 end) as does_not_have_c,
from table1 t1
group by column1

Counting columns with a where clause

Is there a way to count a number of columns which has a particular value for each rows in Hive.
I have data which looks like in input and I want to count how many columns have value 'a' and how many column have value 'b' and get the output like in 'Output'.
Is there a way to accomplish this with Hive query?
One method in Hive is:
select ( (case when cl_1 = 'a' then 1 else 0 end) +
(case when cl_2 = 'a' then 1 else 0 end) +
(case when cl_3 = 'a' then 1 else 0 end) +
(case when cl_4 = 'a' then 1 else 0 end) +
(case when cl_5 = 'a' then 1 else 0 end)
) as count_a,
( (case when cl_1 = 'b' then 1 else 0 end) +
(case when cl_2 = 'b' then 1 else 0 end) +
(case when cl_3 = 'b' then 1 else 0 end) +
(case when cl_4 = 'b' then 1 else 0 end) +
(case when cl_5 = 'b' then 1 else 0 end)
) as count_b
from t;
To get the total count, I would suggest using a subquery and adding count_a and count_b.
Use lateral view with explode on the data and do the aggregations on it.
select id
,sum(cast(col='a' as int)) as cnt_a
,sum(cast(col='b' as int)) as cnt_b
,sum(cast(col in ('a','b') as int)) as cnt_total
from tbl
lateral view explode(array(ci_1,ci_2,ci_3,ci_4,ci_5)) tbl as col
group by id

Combining rows with NULL columns

select
COUNT(Table1.ID) as count_shipped,
null as count_shipped
from Table1
where
table1.saleStatus='shipped'
and table1.saleApproved='yes'
union
select
null,
COUNT(Table1.ID) as count_pending
from Table1
where
table1.saleStatus in ('Pending', 'awaiting payment', 'backorder')
This gives this output
count_shipped count_shipped
NULL 5
4 NULL
but I don't want Null I only want 4 5 in one line Can anybody help me how to do this sql server?
You can use a case to sum up your conditions
select sum(case when saleStatus = 'shipped' and table1.saleApproved = 'yes'
then 1
else 0
end) as count_shipped,
sum(case when saleStatus in ('Pending', 'awaiting payment', 'backorder')
then 1
else 0
end) as count_pending
from Table1