Need help rewriting a T-SQL query for results to get displayed in a stacked bar - tsql

I have come up with the following query which gives rise to the below result.
SELECT TOP (100) PERCENT s.UserfName AS ASSIGNEE, e.status, COUNT(*) AS [TOTAL COUNT], CASE WHEN e.status = "Open" THEN 'OPEN' END AS
FROM dbo.t_helpdesktickets AS e INNER JOIN
dbo.t_assetusers AS s ON e.currentlyat = s.UserID
WHERE (e.status IN ('open', 'closed'))
GROUP BY s.UserfName, e.status
How will I rewrite my query to return results as below

Use conditional aggregation:
SELECT
s.UserfName AS ASSIGNEE,
COUNT(CASE WHEN e.status = 'open' THEN 1 END) AS "OPEN",
COUNT(CASE WHEN e.status = 'closed' THEN 1 END) AS "CLOSED"
FROM dbo.t_assetusers AS s
LEFT JOIN dbo.t_helpdesktickets AS e
ON e.currentlyat = s.UserID
GROUP BY
s.UserfName;
Note that I switched to using a left join here, in case certain users might not have any records corresponding to either of the two statuses. Using this approach, the open/closed counts would then show up as zero.

Related

Select distinct on value must appear in group by

I am encountering an error when trying to run the below query: "column "v.visit_id" must appear in the GROUP BY clause or be used in an aggregate function."
My question is that I believe that I am already using this column in an aggregate function on line 2 count(v.visit_id) as total_visits. Does this not count as satisfying the error? I can't add to the GROUP BY directly since that would mess up my output.
My end goal is to select distinct visit IDs while also only grouping the output by physician names.
select distinct on (v.visit_id)
count(v.visit_id) as total_visits,
sum(mad2.nsma1_ans::time - mad.nsma1_ans::time) as or_hours_utilized,
sum(esla1_bt_end[1] - esla1_bt_beg[1]) as total_block_hours,
sum(extract(epoch from mad2.nsma1_ans::time) - extract(epoch from mad.nsma1_ans::time)) /
(sum(extract(epoch from esla1_bt_end[1])) - sum(extract(epoch from esla1_bt_beg[1]))) * 100 as or_percentage,
pt1.phys1_name as surgeon
from visit as v
inner join pat_phy_relation_table as pprt
on pprt.patphys_pat_num = v.visit_id
and pprt.patphys_rel_type = 'ATTENDING'
inner join physician_table1 as pt1
on pt1.phys1_num = pprt.patphys_phy_num
and pt1.phys1_arid = v.visit_arid --need to confirm how to handle ARIDs
inner join ews_location_table2 elt2
on lpad(pt1.phys1_num::varchar, 6, '0') = any (elt2.esla1_bt_surg)
and esla1_loca in ('OR1','OR2','OR3','OR4')
and esla1_date between '2021-09-01' and '2021-09-30'
and esla1_seid = pt1.phys1_arid
inner join multi_app_documentation mad2
on mad2.nsma1_patnum = v.visit_id
and mad2.nsma1_code = 'OROUT' --only pulling visits/physicians with an OROUT
and mad2.nsma1_ans !~ '[x,X,C,END,S]' --removing non-standard data
and mad2.nsma1_ans != '' and mad2.nsma1_ans != '0' and mad2.nsma1_ans != '1' and mad2.nsma1_ans != '0000'
inner join multi_app_documentation mad
on mad.nsma1_patnum = v.visit_id
and mad.nsma1_code = 'ORINTIME' --only pulling visits/physicians with an ORINTIME
where v.visit_admit_date between '2021-09-01' and '2021-09-30'
and v.visit_arid = 5
group by pt1.phys1_name
The problem is distinct on (v.visit_id) is not an aggregate function. You'd need to add it to the group by.
select
distinct on (v.visit_id)
count(v.visit_id) as total_visits,
...
group by v.visit_id, pt1.phys1_name
However, it makes no sense to use distinct on something you're grouping by. The group by will already only show one row for each visit_id.
select
v.visit_id,
count(v.visit_id) as total_visits,
...
group by v.visit_id, pt1.phys1_name
If v.visit_id is a primary key or unique this also makes no sense. Each visit_id will only appear once and your count will always be 1. You probably want to leave it out entirely.
select
count(v.visit_id) as total_visits
...
group by pt1.phys1_name

Query where ALL associated records have attribute value X

I have a query that counts associated records AND associated status
SELECT
orders.id,
SUM(CASE WHEN s.shipment_status='CLOSED' THEN 1 ELSE 0 END) as closed,
COUNT(*) as shipment_count
FROM orders as po
JOIN shipments as s ON s.order_id = po.id
GROUP BY po.id
I am attempting to query all orders, where all the shipments are CLOSED.
Essentially looking at the above, just returning when closed = shipment_count .
If I add an AND clause to the join then it will simply limit the number of shipments.
I figured this out with a HAVING clause, which doesn't use the select attrs.
SELECT
orders.id
FROM orders as po
JOIN shipments as s ON s.order_id = po.id
GROUP BY po.id
HAVING SUM(CASE WHEN s.shipment_status='CLOSED' THEN 1 ELSE 0 END) = COUNT(*)
Leaving my answer up in case it helps others. Maybe better answers available to come from the community.

Postgresql count by past weeks

select id, wk0_count
from teams
left join
(select team_id, count(team_id) as wk0_count
from (
select created_at, team_id, trunc(EXTRACT(EPOCH FROM age(CURRENT_TIMESTAMP,created_at)) / 604800) as wk_offset
from loan_files
where loan_type <> 2
order by created_at DESC) as t1
where wk_offset = 0
group by team_id) as t_wk0
on teams.id = t_wk0.team_id
I've created the query above that shows me how many loans each team did in a given week. Week 0 is the past seven days.
Ideally I want a table that shows how many loans each team did in the last 8 weeks, grouped by week. The output would look like:
Any ideas on the best way to do this?
select
t.id,
count(week = 0 or null) as wk0,
count(week = 1 or null) as wk1,
count(week = 2 or null) as wk2,
count(week = 3 or null) as wk3
from
teams t
left join
loan_files lf on lf.team_id = t.id and loan_type <> 2
cross join lateral
(select (current_date - created_at::date) / 7 as week) w
group by 1
In 9.4+ versions use the aggregate filter syntax:
count(*) filter (where week = 0) as wk0,
lateral is from 9.3. In a previous version move the week expression to the filter condition.
How about the following query?
SELECT team_id AS id, count(team_id) AS wk0_count
FROM teams LEFT JOIN loan_files ON teams.id = team_id
WHERE loan_type <> 2
AND trunc(EXTRACT(epoch FROM age(CURRENT_TIMESTAMP, created_at)) / 604800) = 0
GROUP BY team_id
Notable changes are:
ORDER BY clause in subquery was pointless;
created_at in innermost subquery was never used;
wk_offset test is moved on the WHERE clause and not done in two distinct steps;
outermost subquery was not needed.

Show Rows Data Into Column Wise

i wants to show rows data into columns. suppose if rows type increased then number of columns also increased. Information as follow:
Please see picture to get idea
You can use COUNT with CASE WHEN:
SELECT t.Name AS Type,
COUNT(*) AS NumberOfCase,
COUNT(CASE WHEN s.Name = 'Resolved' THEN 1 END) AS Resolved,
COUNT(CASE WHEN s.Name = 'Pending' THEN 1 END) AS Pending,
COUNT(CASE WHEN s.Name = 'Waiting' THEN 1 END) AS Waiting
FROM Type t
LEFT JOIN "Case" c
ON c.CaseType = t.TypeId
LEFT JOIN "Status" s
ON c.CaseStatus = s.StatusId
GROUP BY t.Name;
SqlFiddleDemo

How to write a select case join?

I am trying to some sql code that combines information from 2 tables and uses case but it is not returning all the data.
SELECT TABLE1.PRODUCT, TABLE1.TYPE, TABLE1.AMOUNT,
(CASE
WHEN TABLE1.PRODUCT = 'RADIO'
THEN 100
ELSE 200
END) AS PRODUCT_CODE,
(CASE
WHEN TABLE1.TYPE = 'NEW'
THEN 'Y'
ELSE TABLE2.AGE
END) AS STATUS
FROM TABLE1 LEFT JOIN TABLE 2 ON TABLE1.TID = TABLE2.TID
WHERE TABLE1.DATE > '01-AUG-15'
AND TABLE2.DATE = '02-AUG-15'
The problem I am having is that I need all records from table1 and those that apply from table2 but when the query is returning less rows than there are in table 1.
Your problem is here
AND TABLE2.DATE = '02-AUG-15'
If Table2.Date is null due to the left join, this condition fails, which is why you are getting less rows than Table1. Adding a condition to the where clause from a left joined table is effectively turning it into an inner join.
Try either
AND (TABLE2.DATE = '02-AUG-15' OR TABLE2.DATE IS NULL)
(this assumes that TABLE2.DATE is not nullable) or put the condition in the join statement instead
FROM TABLE1 LEFT JOIN TABLE 2 ON TABLE1.TID = TABLE2.TID AND TABLE2.DATE = '02-AUG-15'