I have a query regarding my report, the report format is as under
**Date** **Received** **Closed** **Pending**
12/01/10 1000 900 100
12/02/10 2000 1000 1000
12/03/10 1500 1300 200
The above report shows the Help Desk tickets Received, Closed, Pending Count as date wise.
How can I create a dynamic SQL query to show above result?
Received Tickets is calculated on SubmitedDate
Closed Tickets is calculated on ClosedDate with status "Closed"
same for Pending Tickets whose status is "Pending".
Please provide me the idea or some sample SQL queries.
Write the received, closed, and pending queries separately, and then join them together like this:
SELECT r.[Date], r.Count As Received, c.Count As Closed, p.Count AS Pending
FROM
( /* Received query here */ ) r
FULL JOIN
( /* Closed query here */) c ON c.[Date] = r.[Date]
FULL JOIN
( /* Pending query here */) p ON p.[Date] = r.[Date]
I chose a full join because you wouldn't want a zero-result at any point to ever force a row to be culled from the results.
Use:
SELECT CONVERT(VARCHAR, t.submitteddate, 101) AS [date].
COUNT(t.submitteddate) AS received
SUM(CASE WHEN t.status = 'closed' THEN 1 ELSE 0 END) AS closed,
SUM(CASE WHEN t.status = 'pending' THEN 1 ELSE 0 END) AS pending
FROM YOUR_TABLE t
GROUP BY CONVERT(VARCHAR, t.submitteddate, 101)
ORDER BY [date]
If you want to see dates where none were sold, you're going to have to derive a table of dates and then LEFT JOIN the query above to that based on the date.
Related
I'm trying to use a nested aggregate function. I know that SQL does not support it, but I really need to do something like the below query. Basically, I want to count the number of users for each day. But I want to only count the users that haven't completed an order within a 15 days window (relative to a specific day) and that have completed any order within a 30 days window (relative to a specific day). I already know that it is not possible to solve this problem using a regular subquery (it does not allow to change subquery values for each date). The "id" and the "state" attributes are related to the orders. Also, I'm using Fivetran with Snowflake.
SELECT
db.created_at::date as Date,
count(case when
(count(case when (db.state = 'finished')
and (db.created_at::date between dateadd(day,-15,Date) and dateadd(day,-1,Date)) then db.id end)
= 0) and
(count(case when (db.state = 'finished')
and (db.created_at::date between dateadd(day,-30,Date) and dateadd(day,-16,Date)) then db.id end)
> 0) then db.user end)
FROM
data_base as db
WHERE
db.created_at::date between '2020-01-01' and dateadd(day,-1,current_date)
GROUP BY Date
In other words, I want to transform the below query in a way that the "current_date" changes for each date.
WITH completed_15_days_before AS (
select
db.user as User,
count(case when db.state = 'finished' then db.id end) as Completed
from
data_base as db
where
db.created_at::date between dateadd(day,-15,current_date) and dateadd(day,-1,current_date)
group by User
),
completed_16_days_before AS (
select
db.user as User,
count(case when db.state = 'finished' then db.id end) as Completed
from
data_base as db
where
db.created_at::date between dateadd(day,-30,current_date) and dateadd(day,-16,current_date)
group by User
)
SELECT
date(db.created_at) as Date,
count(distinct case when comp_15.completadas = 0 and comp_16.completadas > 0 then comp_15.user end) as "Total Users Churn",
count(distinct case when comp_15.completadas > 0 then comp_15.user end) as "Total Users Active",
week(Date) as Week
FROM
data_base as db
left join completadas_15_days_before as comp_15 on comp_15.user = db.user
left join completadas_16_days_before as comp_16 on comp_16.user = db.user
WHERE
db.created_at::date between '2020-01-01' and dateadd(day,-1,current_date)
GROUP BY Date
Does anyone have a clue on how to solve this puzzle? Thank you very much!
The following should give you roughly what you want - difficult to test without sample data but should be a good enough starting point for you to then amend it to give you exactly what you want.
I've commented to the code to hopefully explain what each section is doing.
-- set parameter for the first date you want to generate the resultset for
set start_date = TO_DATE('2020-01-01','YYYY-MM-DD');
-- calculate the number of days between the start_date and the current date
set num_days = (Select datediff(day, $start_date , current_date()+1));
--generate a list of all the dates from the start date to the current date
-- i.e. every date that needs to appear in the resultset
WITH date_list as (
select
dateadd(
day,
'-' || row_number() over (order by null),
dateadd(day, '+1', current_date())
) as date_item
from table (generator(rowcount => ($num_days)))
)
--Create a list of all the orders that are in scope
-- i.e. 30 days before the start_date up to the current date
-- amend WHERE clause to in/exclude records as appropriate
,order_list as (
SELECT created_at, rt_id
from data_base
where created_at between dateadd(day,-30,$start_date) and current_date()
and state = 'finished'
)
SELECT dl.date_item
,COUNT (DISTINCT ol30.RT_ID) AS USER_COUNT
,COUNT (ol30.RT_ID) as ORDER_COUNT
FROM date_list dl
-- get all orders between -30 and -16 days of each date in date_list
left outer join order_list ol30 on ol30.created_at between dateadd(day,-30,dl.date_item) and dateadd(day,-16,dl.date_item)
-- exclude records that have the same RT_ID as in the ol30 dataset but have a date between 0 amd -15 of the date in date_list
WHERE NOT EXISTS (SELECT ol15.RT_ID
FROM order_list ol15
WHERE ol30.RT_ID = ol15.RT_ID
AND ol15.created_at between dateadd(day,-15,dl.date_item) and dl.date_item)
GROUP BY dl.date_item
ORDER BY dl.date_item;
I'm trying to count if a member opened a product within 60 days of opening their membership with us.With the code I currently have, I'm showing no one has, which I know is not true, so I have to be doing something wrong. Any ideas?
SELECT M.MEMBER_NBR, COUNT(CASE WHEN S.OPEN_DATE <= DATEADD(d, -60, l.open_date) THEN 1 ELSE NULL END)
FROM LOAN AS L
INNER JOIN APPLICATION AS A ON L.LOAN_NOTE_NBR = A.APLNUM
INNER JOIN MEMBERSHIP AS M ON L.MEMBER_NBR=M.MEMBER_NBR
INNER JOIN SHARE AS S on M.MEMBER_NBR=S.MEMBER_NBR
WHERE l.open_date = M.open_date
GROUP BY M.MEMBER_NBR
ORDER BY COUNT(CASE WHEN S.OPEN_DATE <= DATEADD(d, -60, l.open_date) THEN 1 ELSE NULL END) DESC
EDIT TO PROVIDE Additional data:
I'm trying to see how many members who come to us for a loan open up an additional service (checking account) within 60 days. To do this, I need to compare the Share Open Date (S.Open_date) to see if it occurred within a 60 day window of the loan open date (l.open_date).
For Example:
Member_NBR Share S.Open_Date Loan_Nbr L.Open_Date
1 1 6/29/2020
1 101 6/15/2020
So in the example above, they member opened up a checking account 2 weeks after signing a loan. So with the output, I'd like it to show
Member_Nbr Open_ShareCount
1 1
Or if they opened up a checking and a savings, it would say 2 under Open_ShareCount
Making some assumptions on how the data looks and ignored both the application and membership tables for this answer. Adjust as needed.
Here's the sample data I used...
sample data image
The green highlighted rows are one's that will not appear in the results because the dates are out of bounds.
Query....
select member_number,
count(distinct share) as accounts_opened
from (
select s.member_number
,s.share
--,s.open_date as share_open --kept for QA
--,l.open_date as loan_open --kept for QA
from share s
join loan l on l.member_number = s.member_number
where 1=1
and s.open_date between l.open_date
and l.open_date + '1 day'::interval * 60
)z
group by 1
order by 1
I am creating a query that contains multiple sub-queries that show number of incidents in different status/category/etc. A date filter will need to be applied to all sub-queries, in order to count number of incidents created within the date range.
Because the report will be moved to Business Objects, I cannot specify the dates multiple times in the sub-queries. Hence I joined the incident table (inc) in the sub-queries with another incident table (inc_filter) in the outer query, and hoping to apply one date filter to all sub queries.
But the result returned was incorrect, I got multiple rows that have the value either 0 or 1.
Could anyone please point me to the right direction?
SELECT
(SELECT COUNT(*)
FROM Incident inc
WHERE inc.id = inc_filter.id
AND inc.status = 'Open')
"Total # of Open Inc",
(SELECT COUNT(*)
FROM Incident inc
WHERE inc.id = inc_filter.id
AND inc.status = 'Closed')
"Total # of Closed Inc"
--more sub-queries here...
FROM Incident inc_filter
AND inc_filter.CREATED > '10-Apr-2017'
AND inc_filter.CREATED < '13-Apr-2017'
You are probably simply looking for conditional aggregation:
SELECT
COUNT(CASE WHEN status = 'Open' THEN 1 END) AS "Total # of Open Inc",
COUNT(CASE WHEN status = 'Closed' THEN 1 END) AS "Total # of Closed Inc"
-- more counts here...
FROM Incident
WHERE created >= DATE '2017-04-10' AND created < DATE '2017-04-13';
First you should use case and you dont need use many subquery,
second if i understood your question you should use sum() like this
SELECT sum(case when inc_filter.status = 'Open' then 1 else 0 end) as open,
sum(case when inc_filter.status = 'Closed' then 1 else 0 end) as closed
FROM Incident inc_filter
AND inc_filter.CREATED > '10-Apr-2017'
AND inc_filter.CREATED < '13-Apr-2017'
Dear you need one more select above this with using sum of your count. actually you are using group function but that is apply on row level. you need you sum all your subquery columns to see the required result for example your query will be
select sum("Total # of Open Inc") ,sum("Total # of Closed Inc")
from(
SELECT
(SELECT COUNT(*)
FROM Incident inc
WHERE inc.id = inc_filter.id
AND inc.status = 'Open')
"Total # of Open Inc",
(SELECT COUNT(*)
FROM Incident inc
WHERE inc.id = inc_filter.id
AND inc.status = 'Closed')
"Total # of Closed Inc"
--more sub-queries here...
FROM Incident inc_filter
AND inc_filter.CREATED > '10-Apr-2017'
AND inc_filter.CREATED < '13-Apr-2017');
But it is better for you to use joins
I have 2 separate queries below which run correctly.Now I've created a calculated column to provide a count of working days by YMs and would like to bring this through to query1(the join would be query1.Period = query2.Yms)
please see the query and outputs below.
SELECT Client, ClientGroup, Type, Value, Period, PeriodName, PeriodNumber, ClientName
FROM metrics.dbo.vw_KPI_001_Invoice
select YMs,sum(case when IsWorkDay = 'X' then 1 else 0 end) from IESAONLINE.Dbo.DS_Dates
where Year > '2013'
group by YMs
Query 1
Client ClientGroup Type Value Period PeriodName PeriodNumber ClientName
0LG0 KarroFoods Stock 5691.68 201506 Week 06 2015 35 Karro Foods Scunthorpe
Query 2
YMs (No column name)
201401 23
Would the following work:
SELECT Client, ClientGroup, Type, Value, Period, PeriodName, PeriodNumber, ClientName, cnt
FROM metrics.dbo.vw_KPI_001_Invoice q1
INNER JOIN (select YMs,sum(case when IsWorkDay = 'X' then 1 else 0 end) as cnt from IESAONLINE.Dbo.DS_Dates
where Year > '2013'
group by YMs ) q2 ON q1.Period = q2.YMs
If a value isn't always available then you might consider changing the INNER JOIN to an OUTER JOIN.
I am currently working on aggregating the sum qty of "OUT" and "OUT+IN".
Current query is the following:
Select
a.Date
,a.DepartmentID
from
(Select
dris.Date
,dris.RentalItemKey
,dris.WarehouseKey
,ISNULL((Select TOP 1 dris.Date where OutQty=1 order by Date DESC),(Select ri.ReceiveDate from RentalItem ri where ri.RentalItemKey=dris.RentalItemKey)) as LastOutDate
,(Select d.DepartmentKey from Department d where d.Department=i.Department)as DepartmentID
, (CASE WHEN OutQty=1 OR (RepairQty=1 AND RentedQty=1) THEN 'IN' ELSE 'OUT' END) as Status
from DailyRentalItemStatus dris
inner join Inventory i on i.InventoryKey=dris.InventoryKey
where dris.Date='2014-08-02'
and i.ICode='3223700'
and i.Classification IN ('ITEM', 'ACCESSORY')
and i.AvailFor='RENT'
and i.AvailFrom='WAREHOUSE'
and dris.Warehouse='TORONTO')a
and I would like the result to be the following:
Date WarehouseID DepartmentID ICode Owned NotRedundant Out
2014-08-02 001T A00G 3223700 30 30 19
Where Owned is is The items with status as "OUT+IN", out is "OUT" and Not Redundant as where the lastout date is within the last 2 years from the date.
Help would be greatly appreciated.
I think this is close to what you're looking for. Your Not Redundant description, is hard to understand. Which dates are you comparing. The same trick for OUT may be used for that though.
My query also assumes that you always have a department connecting to the inventory table and that there's always a rentalitem.receivedate.
;WITH LastOut as
(Select Max(Date) as LastOutDate, rentalItemKey
from DailyRentalItemStatus
WHERE OutQty=1
)
Select
dris.Date
,dris.WarehouseKey as WarehouseID
,d.DepartmentKey as DepartmentID
, i.Icode
--,ISNULL((Select TOP 1 dris.Date where OutQty=1 order by Date DESC),(Select ri.ReceiveDate from RentalItem ri where ri.RentalItemKey=dris.RentalItemKey)) as LastOutDate
, Count(1) as Owned
, Sum(CASE WHEN NOT (OutQty=1 OR (RepairQty=1 AND RentedQty=1)) THEN 1 ELSE 0 END) as OUT
, Sum(CASE WHEN DateAdd(yy, 2,dris.[date]) >= ISNULL(lastout.lastoutdate, ri.ReceiveDate) then 1 else 0 end) as NonRedundent
from DailyRentalItemStatus dris
inner join Inventory i on i.InventoryKey=dris.InventoryKey
INNER JOIN Department d ON d.Department=i.Department
INNER JOIN RentalItem ri ON ri.RentalItemKey=dris.RentalItemKey
LEFT OUTER JOIN LastOUT ON LastOut.rentalItemKey=dris.RentalItemKey
where dris.Date='2014-08-02'
and i.ICode='3223700'
and i.Classification IN ('ITEM', 'ACCESSORY')
and i.AvailFor='RENT'
and i.AvailFrom='WAREHOUSE'
and dris.Warehouse='TORONTO'
Group BY dris.Date, d.DepartmentKey, Dris.WarehouseKey , i.icode