How to group difference of date values by range [closed] - sql

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 years ago.
Improve this question
I have strung together a series of queries that I have had working as individual queries or as a query with one subquery.
I need to show the total number of jobs that have a particular status grouped by range of the number of days a job has been in that status.
E.g. (random data for concept purpose)
fldFranchiseCode Status 0-9 10-19 20-29 etc
Franchise A Status1 1 0 3
Franchise A Status2 2 1 4
Franchise A Status4 3 2 1
Franchise B Status2 1 6 4
This is what I have so far, but I'm getting a SQL error - 'Incorrect syntax near 'pvt'.'
SELECT * FROM
(SELECT fldFranchiseCode, Range AS [Day Range], COUNT(*) AS Jobs
FROM (SELECT fldFranchiseCode, CASE WHEN Days BETWEEN 0 AND 9 THEN '0- 9'
WHEN Days BETWEEN 10 AND 19 THEN '10-19'
WHEN Days BETWEEN 20 AND 29 THEN '20-29'
WHEN Days BETWEEN 30 AND 39 THEN '30-39'
WHEN Days BETWEEN 40 AND 49 THEN '40-49'
WHEN Days BETWEEN 50 AND 59 THEN '50-59'
WHEN Days BETWEEN 60 AND 69 THEN '60-69'
WHEN Days BETWEEN 70 AND 79 THEN '70-79'
WHEN Days BETWEEN 80 AND 89 THEN '80-89'
WHEN Days BETWEEN 90 AND 99 THEN '90-99'
ELSE 'Over 100' END AS Range
FROM (SELECT fldRecordID,
T.fldInquiryRecordID,
fldDate,
NextDate,
DATEDIFF("D", fldDate, NextDate) AS Days,
fldStatus,
fldFranchiseCode
FROM ( SELECT fldRecordID,
T1.fldInquiryRecordID,
fldDate,
( SELECT MIN([fldDate])
FROM tblStatusLog T2
WHERE T2.[fldInquiryRecordID] = T1.[fldInquiryRecordID]
AND T2.[fldDate] > T1.[fldDate]
) AS NextDate,
fldStatus,
fldFranchiseCode
FROM tblStatusLog T1
JOIN tblInquiry ON T1.fldInquiryRecordID = tblInquiry.fldInquiryRecordID
) AS T
GROUP BY [Day Range],fldFranchiseCode) q1
pivot
(max(jobs)
FOR [Day Range] IN ([0- 9],[10-19],[20-29],[30-39],[40-49],[50-59],
[60-69],[70-79],[80-89],[90-99],[Over 100])
)as pvt
Any help much appreciated

Proper indenting will help identify the syntax error. (Well, or avoiding nesting queries four levels deep in the first place.)
SELECT * FROM
(
SELECT fldFranchiseCode, ...
FROM
(
SELECT fldFranchiseCode, CASE ...
FROM
(
SELECT fldRecordID, ...
FROM
(
SELECT fldRecordID, ...
FROM tblStatusLog T1
JOIN tblInquiry ON T1.fldInquiryRecordID = tblInquiry.fldInquiryRecordID
) AS T
GROUP BY Range, fldFranchiseCode
^^^^^ note, can't group by an alias here
) q1
) AS q2 -- you need this one
) AS q3 -- and this one too
pivot
(
max(jobs)
FOR [Day Range] IN ([0- 9],[10-19],[20-29],[30-39],[40-49],[50-59],
[60-69],[70-79],[80-89],[90-99],[Over 100])
) as pvt;

Related

How to aggregate event dates based on aggregated table? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 16 days ago.
Improve this question
I have a table that aggregates disables/reenables events in the following format:
Disabled Date
Enabled Date
Count
01/01
01/01
5
01/01
02/01
2
03/01
05/01
1
04/01
05/01
5
and want to build a report that aggregates the number of disables and reenables per day:
Date
Enables
Disables
01/01
5
7
02/01
2
0
03/01
0
1
04/01
0
5
05/01
6
0
I was able to build the following query that works for days that have at least one disable and one enable:
SELECT
disables.disable_date AS disable_date,
disables.disable_count disable_count,
enables.enable_count enable_count
FROM
(SELECT
disable_date,
sum(disable_count) disable_count
FROM table
GROUP BY 1) AS disables,
(SELECT
enable_date,
sum(disable_count) enable_count
FROM table
GROUP BY 1) AS enables
WHERE enables.enable_date = disables.disable_date;
Any suggestions how to build the complete output? I'm not sure this is the right strategy, so a JOIN could also be considered.
Thanks!
;WITH cte
AS (SELECT disabled_date AS Date,
Sum(count) AS Disables
FROM table1
GROUP BY disabled_date
UNION ALL
SELECT enabled_date AS Date,
Sum(-count) AS Disables
FROM table1
GROUP BY enabled_date)
SELECT cte.date,
COALESCE(Sum(CASE
WHEN cte.disables > 0 THEN cte.disables
END), 0) AS Enables,
COALESCE(Sum(CASE
WHEN cte.disables < 0 THEN -cte.disables
END), 0) AS Disables
FROM cte
GROUP BY cte.date
ORDER BY cte.date;
TEST
http://sqlfiddle.com/#!18/13cace/3

arithmetic operation on alias of column of table [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last month.
Improve this question
I have written a query which fetch the data like this and I wanted to calculate the opening and maindata I have formula for then which is ( CurrentEmp + Empjoined - EmpLeft ) as opening and ((EmpLeft*100)/((CurrentEmp+opening)/2)) as maindata respectively I have written it in query but I gets the error saying invalid column name .
month year CurrentEmp join leftemp
January 2021 10 2 1
February 2021 15 3 2
March 2021 20 5 2
and the output that I expect is
month year CurrentEmp join leftemp opening
January 2021 10 2 1 11
February 2021 15 3 2 16
March 2021 20 5 2 23
I have written the below code
with t0(n) as ( select n from ( values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) t(n)),ns as(select row_number()
over(order by t1.n) - 1 n from t0 t1, t0 t2, t0 t3),calendar as (
select top(12) DATEADD(month, n, '2021-01-01' ) dt , DATEADD(month, n , '2021-01-31')dd from ns order by n) select cast(DATENAME(month, dt) as nvarchar(max)) AS month,cast(DATENAME(YEAR, dt) as nvarchar(max))AS Year,
(SELECT COUNT(*) FROM EmployeeDetail e left join Separation s on e.Id = s.EmployeeId
WHERE (e.CompanyId=1 and e.DateOfJoining <calendar.dt and e.EmpStatus = 1) or(s.CompanyId = 1 and e.DateOfJoining <calendar.dt and s.LastWorkingDate >= calendar.dt)) AS CurrentEmp,
(select count(*) from EmployeeDetail where DateOfJoining >=calendar.dt And DateOfJoining<=calendar.dd and CompanyId = 1) as Empjoined,
(select count(*) from Separation where LastWorkingDate >= calendar.dt and LastWorkingDate < =calendar.dd and CompanyId =1) as EmpLeft,
(CurrentEmp+Empjoined-EmpLeft) as opening , cast (((EmpLeft*100)/((CurrentEmp+opening)/2)) as decimal(10,2)) as maindata
from calendar order by dt
An alias in the current select statement cannot be used as a variable within that same select statement.
You'll need to either:
Repeat the calculation:
(CurrentEmp+Empjoined-EmpLeft) as opening,
-- NOTE: opening IS REPLACED BY SAME CALC: (CurrentEmp+Empjoined-EmpLeft)
cast (((EmpLeft*100) /
((CurrentEmp+(CurrentEmp+Empjoined-EmpLeft))/2))
as decimal(10,2)) as maindata
Or, move the primary calculation of opening to a sub-query and join on that.
But, given the simplicity and low overhead of the calculation, I'd just repeat the calculation.

See the distribution of secondary requests grouped by time interval in sql

I have the following table:
RequestId,Type, Date, ParentRequestId
1 1 2020-10-15 null
2 2 2020-10-19 1
3 1 2020-10-20 null
4 2 2020-11-15 3
For this example I am interested in the request type 1 and 2, to make the example simpler. My task is to query a big database and to see the distribution of the secondary transaction based on the difference of dates with the parent one. So the result would look like:
Interval,Percentage
0-7 days,50 %
8-15 days,0 %
16-50 days, 50 %
So for the first line from teh expected result we have the request with the id 2 and for the third line from the expected result we have the request with the id 4 because the date difference fits in this interval.
How to achieve this?
I'm using sql server 2014.
We like to see your attempts, but by the looks of it, it seems like you're going to need to treat this table as 2 tables and do a basic GROUP BY, but make it fancy by grouping on a CASE statement.
WITH dateDiffs as (
/* perform our date calculations first, to get that out of the way */
SELECT
DATEDIFF(Day, parent.[Date], child.[Date]) as daysDiff,
1 as rowsFound
FROM (SELECT RequestID, [Date] FROM myTable WHERE Type = 1) parent
INNER JOIN (SELECT ParentRequestID, [Date] FROM myTable WHERE Type = 2) child
ON parent.requestID = child.parentRequestID
)
/* Now group and aggregate and enjoy your maths! */
SELECT
case when daysDiff between 0 and 7 then '0-7'
when daysDiff between 8 and 15 then '8-15'
when daysDiff between 16 and 50 THEN '16-50'
else '50+'
end as myInterval,
sum(rowsFound) as totalFound,
(select sum(rowsFound) from dateDiffs) as totalRows,
1.0 * sum(rowsFound) / (select sum(rowsFound) from dateDiffs) * 100.00 as percentFound
FROM dateDiffs
GROUP BY
case when daysDiff between 0 and 7 then '0-7'
when daysDiff between 8 and 15 then '8-15'
when daysDiff between 16 and 50 THEN '16-50'
else '50+'
end;
This seems like basically a join and group by query:
with dates as (
select 0 as lo, 7 as hi, '0-7 days' as grp union all
select 8 as lo, 15 as hi, '8-15 days' union all
select 16 as lo, 50 as hi, '16-50 days'
)
select d.grp,
count(*) as cnt,
count(*) * 1.0 / sum(count(*)) over () as raio
from dates left join
(t join
t tp
on tp.RequestId = t. ParentRequestId
)
on datediff(day, tp.date, t.date) between d.lo and d.hi
group by d.grp
order by d.lo;
The only trick is generating all the date groups, so you have rows with zero values.

How to group by quarters(1 year = 4 quarters) in SQL? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Question Description:Show for each customer and product combination, the average sales quantities for 4 quarters,Q1, Q2, Q3 and Q4(in four separate columns) –Q1 being the first 3 months of the year (Jan, Feb & Mar), Q2 the next 3 months (Apr, May & Jun), and so on–ignore the YEAR component of the dates (i.e., 3/11/2001is considered the same date as 3/11/2002, etc.).Also compute the average for the “whole” year(again ignoring the YEAR component, meaning simply compute AVG) along with the total quantities(SUM) and the counts(COUNT).
table as follow:enter image description here
The sample result:enter image description here
I am a beginner on SQL and I met such a problem. It needs to group the 4 quarters just by using aggregate functions and group by clause.
with cte as (
select
customer,
product,
case
when (month < 4) then 'Q1'
when (month >= 4 AND month < 7) then 'Q2'
when (month >= 7 AND month < 10) then 'Q3'
when (month >= 10) then 'Q4'
end AS quarter,
quant
from bgg.table_sof
),
cte_full as (
select
customer,
product,
avg(quant) as average,
sum(quant) as total,
count(quant) as count
from bgg.table_sof
GROUP BY customer, product
)
select
cte_full.customer,
cte_full.product,
avg(cte1.quant) as Q1_AVG,
avg(cte2.quant) as Q2_AVG,
avg(cte3.quant) as Q3_AVG,
avg(cte4.quant) as Q4_AVG,
average,
total,
count
from cte_full
left join cte cte1 on cte_full.customer = cte1.customer and cte_full.product = cte1.product
left join cte cte2 on cte_full.customer = cte2.customer and cte_full.product = cte2.product
left join cte cte3 on cte_full.customer = cte3.customer and cte_full.product = cte3.product
left join cte cte4 on cte_full.customer = cte4.customer and cte_full.product = cte4.product
where cte1.quarter = 'Q1' OR cte2.quarter = 'Q2' OR cte3.quarter = 'Q3' OR cte4.quarter = 'Q4'
group by cte_full.customer, cte_full.product, average, total, count;
It's a tricky task for a beginner. My advice is to start with some theory and easy practice.
There is two CTE (common table expression):
the first is for defining quarters from months.
the second (cte_full) for calculating the last 3 columns in the result table.
And final select joins separately calculated avg by quarters to result.
I'm sure it isn't easy for understanding for beginner, feel free to ask.

SQL First In First Out Loyalty Point

fellow developers and analysts. I have some experience in SQL and have resorted to similar posts. However, this is slightly more niche. Thank you in advance for helping.
I have the below dataset (edited. Apology)
Setup
CREATE TABLE CustomerPoints
(
CustomerID INT,
[Date] Date,
Points INT
)
INSERT INTO CustomerPoints
VALUES
(1, '20150101', 500),
(1, '20150201', -400),
(1, '20151101', 300),
(1, '20151201', -400)
and need to turn it into (edited. The figures in previous table were incorrect)
Any positive amount of points are points earned whereas negative are redeemed. Because of the FIFO (1st in 1st out concept), of the second batch of points spent (-400), 100 of those were taken from points earned on 20150101 (UK format) and 300 from 20151101.
The goal is to calculate, for each customer, the number of points spent within x and y months of earning. Again, thank you for your help.
I have already answered a similar question here and here
You need to explode points earned and redeemed by single units and then couple them, so each point earned will be matched by a redeemed point.
For each of these matching rows calculate the months elapsed from the earning to the redeeming and then aggregate it all.
For FN_NUMBERS(n) it is a tally table, look at other answers I have linked above.
;with
p as (select * from CustomerPoints),
e as (select * from p where points>0),
r as (select * from p where points<0),
ex as (
select *, ROW_NUMBER() over (partition by CustomerID order by [date] ) rn
from e
join FN_NUMBERS(1000) on N<= e.points
),
rx as (
select *, ROW_NUMBER() over (partition by CustomerID order by [date] ) rn
from r
join FN_NUMBERS(1000) on N<= -r.points
),
j as (
select ex.CustomerID, DATEDIFF(month,ex.date, rx.date) mm
from ex
join rx on ex.CustomerID = rx.CustomerID and ex.rn = rx.rn and rx.date>ex.date
)
-- use this select to see points redeemed in current and past semester
select * from j join (select 0 s union all select 1 s ) p on j.mm >= (p.s*6)+(p.s) and j.mm < p.s*6+6 pivot (count(mm) for s in ([0],[2])) p order by 1, 2
-- use this select to see points redeemed with months detail
--select * from j pivot (count(mm) for mm in ([0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])) p order by 1
-- use this select to see points redeemed in rows per month
--select CustomerID, mm, COUNT(mm) PointsRedeemed from j group by CustomerID, mm order by 1
output of default query, 0 is 0-6 months, 1 is 7-12 (age of redemption in months)
CustomerID 0 1
1 700 100
output of 2nd query, 0..12 is the age of redemption in months
CustomerID 0 1 2 3 4 5 6 7 8 9 10 11 12
1 0 700 0 0 0 0 0 0 0 0 0 100 0
output from 3rd query, is the age of redemption in months
CustomerID mm PointsRedeemed
1 1 700
1 11 100
bye