how to get a name from a group by id in sql - sql

I have a table of customers groups and I would like to select the group's names (and another value called Notes) but group by doesn't allow me to do that even though the entire group has the same value of names and notes.
select cg.idCustomerGroup,
sum(case when c.type = 'child' then 1 else 0 end) as Children,
sum(case when c.type = 'adult' then 1 else 0 end) as Adults,
sum(case when c.type = 'senior' then 1 else 0 end) as Seniors
from CustomersGroups cg
inner Join CustomersInGroup cig
on cg.idCustomerGroup = cig.idCustomerGroup
inner Join Customers c
on c.idCustomer = cig.idCustomer
Group by cg.idCustomerGroup

You have to include the group's name and notes in the GROUP BY:
select cg.idCustomerGroup, cg.Name, cg.Notes,
sum(case when c.type = 'child' then 1 else 0 end) as Children,
sum(case when c.type = 'adult' then 1 else 0 end) as Adults,
sum(case when c.type = 'senior' then 1 else 0 end) as Seniors
from CustomersGroups cg
inner Join CustomersInGroup cig
on cg.idCustomerGroup = cig.idCustomerGroup
inner Join Customers c
on c.idCustomer = cig.idCustomer
Group by cg.idCustomerGroup, cg.Name, cg.Notes

Related

Why is my group by not grouping my values as expected?

My project is a clothes factory and I have 3 tables.
Person : A table that contains people's name
Category : Contains each category of clothes in the factory (sockets, shoes, etc.)
Quantity : The quantity of clothes for each person
SELECT Name,
sum(case when category = 'shoes' then quantity else 0 end) as 'Quantity_shoes',
sum(case when category = 'shirts' then quantity else 0 end) as 'Quantity_shirts',
sum(case when category = 'sockets' then quantity else 0 end) as 'Quantity_shirts',
sum(case when category = 'hats' then quantity else 0 end) as 'Quantity_hats'
FROM person p
join inventory i
on i.person_id = p.id
join category c
c.id = i.category_id
WHERE p = 'Paul'
GROUP BY name,
category
And I'm trying to display something like this :
Name
Quantity_shoes
Quantity_shirts
Quantity_sockets
Quantity_hats
Paul
8
25
38
0
But my result isn't that I expected... I got this :
Name
Quantity_shoes
Quantity_shirts
Quantity_sockets
Quantity_hats
Paul
8
0
0
0
Paul
0
0
0
0
Paul
0
25
0
0
Paul
0
0
38
0
It seems that I have one row for each category. So I tried to groupbyquantity but it doesn't sum my quantity and I have more rows.
What I am doing wrong?
As suggested in the above try this (I am guessing the column in person with the name is p.name in which case you may not even need the group by name):
SELECT
Name,
sum(case when category = 'shoes' then quantity else 0 end) as 'Quantity_shoes',
sum(case when category = 'shirts' then quantity else 0 end) as 'Quantity_shirts',
sum(case when category = 'sockets' then quantity else 0 end) as 'Quantity_shirts',
sum(case when category = 'hats' then quantity else 0 end) as 'Quantity_hats'
FROM
person p
join inventory i on i.person_id = p.id
join category c.id = i.category_id
WHERE
p.name = 'Paul'

SQL query that summarizes each group

I need help with this. I need to summarize each group of tests. The result should look like this:
name_of_the_group | all_test_cases | passed_test_cases | total_value
numerical stability 4 4 80
memory usage 3 2 20
corner cases 0 0 0
performance 2 0 0
columns:
name_of_the_group (all groups need to be displayed even if there are no corresponding tests)
all_test_cases (number of tests in the group)
passed_test_cases (number of test cases with the status OK)
total_value (total value of passed tests in this group)
Here is the fiddle example: http://sqlfiddle.com/#!17/e96109
Below SQL query provide a solution to all test cases
When there is a name entry in table test_groups but missing in test_cases.
Order by test_value desc first and then by name lexicographically increasing
order.
SELECT CASE
WHEN g.name = c.group_name THEN c.group_name
ELSE g.name
END AS name,
count(c.group_name) AS all_test_cases,
count(CASE
WHEN c.status = 'OK' THEN 1
END) AS all_test_cases,
sum(CASE
WHEN c.status = 'OK' THEN g.test_value
ELSE 0
END) AS total_value
FROM test_groups g
LEFT JOIN test_cases c ON g.name = c.group_name
GROUP BY CASE
WHEN g.name = c.group_name THEN c.group_name
ELSE g.name
END
ORDER BY total_value DESC,
CASE
WHEN g.name = c.group_name THEN c.group_name
ELSE g.name
END
simple conditional aggregation:
select
t.name,
count(*) as total,
sum(case when c.status = 'OK' then 1 else 0 end) as passed,
sum(case when c.status = 'OK' then test_value end) as score
from
test_groups t
left join test_cases c
on t.name = c.group_name
group by t.name
Fiddle
with all_test_cases as (select name, count(id) as cnt from (
select a.name, a.test_value, b.id, b.status from test_groups a
left join test_cases b on a.name = b.group_name) total_test
group by name),
passed_test_cases as (
select name, count(name) as cnt from (
select a.name, a.test_value, b.id, b.status from test_groups a
join test_cases b on a.name = b.group_name
and b.status = 'OK') OK_test
group by name)
select tg.name, atc.cnt as all_test_cases , coalesce(ptc.cnt, 0) as passed_test_cases, coalesce(ptc.cnt * tg.test_value, 0) as total_value
from test_groups tg
left join all_test_cases atc on tg.name = atc.name
left join passed_test_cases ptc on tg.name = ptc.name
order by total_value desc, name
Select t.name,
sum(case when c.status = 'OK' or c.status = 'ERROR' then 1 else 0 end) as all_test_cases,
sum(case when c.status = 'OK' then 1 else 0 end) as passed_test_cases,
sum(case when c.status = 'OK' then 1 else 0 end) * t.test_value as total_value
from
test_groups t
left join test_cases c
on t.name = c.group_name
group by t.name,t.test_value
order by ,t.total_value,t.name
WITH A AS (SELECT group_name AS name, COUNT(status) AS all_test_cases,
SUM(CASE
WHEN status = 'OK' THEN 1
ELSE 0
END) AS passed_test_cases
FROM test_cases
GROUP BY group_name)
SELECT g.name, IFNULL(c.all_test_cases,0),
IFNULL(c.passed_test_cases,0),
IFNULL(g.test_value*c.passed_test_cases,0) AS total_value
FROM test_groups AS g
LEFT JOIN A AS c
ON g.name = c.name
GROUP BY g.name
ORDER BY total_value DESC;
Select Name Name_Of_The_Group ,Count(Status) All_Test_Cases,
Sum(Case When Status = 'OK' Then 1 Else 0 End) passed_test_cases ,
Sum(Case When Status = 'OK' Then test_value End) total_value
From Test_Cases Full Outer Join Test_Groups On Name = Group_Name
Group By Group_Name,Name
order by Name_Of_The_Group;
Try the following query:
select t.name,
count(c.*)as total,
sum(case when c.status='OK'then 1 else 0 end) as passed,
Case when sum(case when c.status='OK'then test_value end)Is NULL then 0
Else sum(case when c.status='OK'then test_value end)End as total_value
from test_groups t
left join test_cases c on t.name=c.group_name
group by t.name
order by total_value desc,t.name;

Add flag for row existence in another table with group by

For below query I want to have a flag called isHold that will evaluate to 0
if there is no billNo from the view viewBills exists in onHold table and
1 otherwise
select max(t.id) TrackingID , max(vb.billNo) billNo, cb.id ,
max(case when vb.[count] > 1 then 1 else 0 end) isMultiple ,
max(case when t.TrackingID = 31 then 1 else 0 end) IsCancelled,
max(case when exists (select 1 from OnHold oh
where oh.billNo = billNo) then 1 else 0 end) IsHold
from viewBills vb
join tracking t on vb.billNo = t.billNo
join customerBills cb on vb.billNo = cb.billNo
join customerPieces cp on cb.id = cp.customerBillId
where cb.statusid <> 3
group by cb.id
I got this error when executing
Cannot perform an aggregate function on an expression
containing an aggregate or a subquery.
It's reasonable but how can achieve that?
You can use outer apply or a left join to move the logic to the FROM clause:
select max(t.id) as TrackingID , max(vb.billNo) as billNo, cb.id ,
max(case when vb.[count] > 1 then 1 else 0 end) as isMultiple,
max(case when t.TrackingID = 31 then 1 else 0 end) as IsCancelled,
max(case when oh.billNo is not null then 1 else 0 end) as IsHold
from viewBills vb join
tracking t
on vb.billNo = t.billNo join
customerBills cb
on vb.billNo = cb.billNo join
customerPieces cp
on cb.id = cp.customerBillId outer apply
(select top (1) oh.*
from OnHold oh
where oh.billNo = cb.billNo
) oh
where cw.statusid <> 3
group by cb.id;
You can go for LEFT OUTER JOIN and do the aggregation as given below:
select max(t.id) TrackingID , max(vb.billNo) billNo, cb.id ,
max(case when vb.[count] > 1 then 1 else 0 end) isMultiple ,
max(case when t.TrackingID = 31 then 1 else 0 end) IsCancelled,
max(case when oh.billNo IS NOT NULL then 1 else 0 end) IsHold
from viewBills vb
join tracking t on vb.billNo = t.billNo
join customerBills cb on vb.billNo = cb.billNo
join customerPieces cp on cb.id = cp.customerBillId
LEFT OUTER JOIN OnHold oh ON oh.billNo = vb.billNo
where cb.statusid <> 3
group by cb.id

(store procedure) combine result 2 rows into 1 row result

can i combine result row 3 and row 4 into 1 row record?
select #fYear as [Year],
(case when main.Description in ('Kecil', 'Tanah') then 'JK'
else main.Description
end) as description,
--CardType,
sum(case when MONTH(blue.AppliedDate) = 1 then 1 else 0 end) as Jan_Collection,
sum(case when MONTH(blue.AppliedDate) = 2 then 1 else 0 end) as Feb_Collection,
...
from tblR as main
left join tblP as b on main.requestorid = b.requestorid
left join tblB as blue on b.partyid = blue.partyid and YEAR(blue.AppliedDate) = #fYear
group by (case when main.Description in ('Kecil', 'Tanah') then 'JK'
else main.Description
end)
this output like:
https://gyazo.com/d930cb2aee92f90ba31dd543d6ca64f3
but can i display combine record row 3 and 4 into 1 record like JK like this picture: https://gyazo.com/a89ed2fa04b51135bf8601d59d4af0b2
Thanks.
If you want to combine those specific descriptions, you can use a case, both in the select and the group by:
select #fYear as [Year],
(case when description in ('kecil', 'Tanah') then 'JK'
else main.Description
end) as Description,
sum(case when MONTH(blue.AppliedDate) = 1 then 1 else 0 end) as Jan_Collection,
sum(case when MONTH(blue.AppliedDate) = 2 then 1 else 0 end) as Feb_Collection,
...
from tblR main left join
tblP b
on main.requestorid = b.requestorid left join
tblB
blue
on b.partyid = blue.partyid and YEAR(blue.AppliedDate) = #fYear
group by (case when description in ('kecil', 'Tanah') then 'JK'
else main.Description
end)

Combining unrelated queries into one query to produce counts

I would like a stored procedure to run daily that produces a report of counts.
For example, the .csv would look something like this:
Daily,1
Deaths,0
In-House EKG,4
In-House Xray,2
Suicidal Patients,12
HIV,0
Their individual queries look something like this:
-- Daily and Death Counts
select
SUM(CASE WHEN location != '[OUT]' THEN 1 ELSE 0 END) as 'Daily',
SUM(CASE WHEN death = 1 THEN 1 ELSE 0 END) as 'Deaths'
from
patient_data
-- In-House Tasks
select
SUM(CASE WHEN cat_id = 72 THEN 1 ELSE 0 END) as 'In-House EKG',
SUM(CASE WHEN cat_id = 73 THEN 1 ELSE 0 END) as 'In-House XRay',
from
organizer_tasks
-- Suicidal Patients
select
count(distinct(pid)) as 'Suicidal Inmates'
from
problems pr
inner join problem_list pl on pl.id = pr.problem_list_id
where
pr.status = 'open'
and pl.title like '%suicide%'
-- HIV
select
count(distinct(pid)) as 'HIV'
from
problems pr
inner join problem_list pl on pl.id = pr.problem_list_id
inner join patient_data pd on pr.pid = pd.pid
where
pr.status = 'open'
and pl.title like '%hiv%'
As you can see, each set of data comes from a different table, and has no relation. How can I accomplish my desired result set?
Thanks.
-- Daily and Death Counts
select * from (
select
SUM(CASE WHEN location != '[OUT]' THEN 1 ELSE 0 END) as 'Daily',
SUM(CASE WHEN death = 1 THEN 1 ELSE 0 END) as 'Deaths'
from
patient_data
) tmp unpivot (Number for Type in ([Daily], [Deaths])) t
union all
-- In-House Tasks
select * from (
select
SUM(CASE WHEN cat_id = 72 THEN 1 ELSE 0 END) as 'In-House EKG',
SUM(CASE WHEN cat_id = 73 THEN 1 ELSE 0 END) as 'In-House XRay'
from
organizer_tasks
) tmp unpivot (Number for Type in ([In-House EKG], [In-House XRay])) t
union all
-- Suicidal Patients
select 'Suicidal Inmates',
count(distinct(pid))
from
problems pr
inner join problem_list pl on pl.id = pr.problem_list_id
where
pr.status = 'open'
and pl.title like '%suicide%'
union all
-- HIV
select 'HIV',
count(distinct(pid))
from
problems pr
inner join problem_list pl on pl.id = pr.problem_list_id
inner join patient_data pd on pr.pid = pd.pid
where
pr.status = 'open'
and pl.title like '%hiv%'
Try this with Union which is form in one Query :
select
SUM(CASE WHEN location != '[OUT]' THEN 1 ELSE 0 END) as 'Daily'
from
patient_data
UNION ALL
select
SUM(CASE WHEN death = 1 THEN 1 ELSE 0 END) as 'Deaths'
from
patient_data
UNION ALL
-- In-House Tasks
select
SUM(CASE WHEN cat_id = 72 THEN 1 ELSE 0 END) as 'In-House EKG'
from
organizer_tasks
UNION ALL
select
SUM(CASE WHEN cat_id = 73 THEN 1 ELSE 0 END) as 'In-House XRay'
from
organizer_tasks
UNION ALL
-- Suicidal Patients
select
count(distinct(pid)) as 'Suicidal Inmates'
from
problems pr
inner join problem_list pl on pl.id = pr.problem_list_id
where
pr.status = 'open'
and pl.title like '%suicide%'