How can I accomplish this? Would a cursor be appropriate? - sql

I am trying to use TOAD and T-SQL to approximate a user's spreadsheet. Here are the basics of what they want:
Order Number Customer Name June July Aug Sept Oct Nov Dec
12345 Bleh Company 1000
800 200
The first row represents when the order value was received and the second represents the projected ship date of said order.
The following SQL Script delivers this, but it does not alternate between Order Date and Receiving Date.
SELECT 'O', -- For Order Date
(SOM.[fcustno] + ' - ' + SOM.[fcompany]) AS [Customer],
sum(CASE month (SOM.forderdate)
WHEN 6 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [June],
sum(CASE month (SOM.forderdate)
WHEN 7 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [July],
sum(CASE month (SOM.forderdate)
WHEN 8 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [Aug],
sum(CASE month (SOM.forderdate)
WHEN 9 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [Sept],
sum(CASE month (SOM.forderdate)
WHEN 10 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [Oct],
sum(CASE month (SOM.forderdate)
WHEN 11 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [Nov],
sum(CASE month (SOM.forderdate)
WHEN 12 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [Dec]
FROM SORELS SOR
JOIN SOMAST SOM
ON SOM.FSONO = SOR.FSONO
JOIN SOITEM SOI
ON SOI.FSONO = SOR.FSONO AND SOI.FINUMBER = SOR.FINUMBER
WHERE FMASTERREL = 0
AND SOM.forderdate >= CONVERT (DATETIME, '05/29/2009')
AND SOM.forderdate < CONVERT (DATETIME, '08/04/2009')
AND SOI.fduedate < CONVERT (DATETIME, '01/01/2010')
GROUP BY (SOM.[fcustno] + ' - ' + SOM.[fcompany])
UNION
SELECT 'S', -- For Ship Date
(SOM.[fcustno] + ' - ' + SOM.[fcompany]) AS [Customer],
sum(CASE month (SOI.fduedate)
WHEN 6 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [June],
sum(CASE month (SOI.fduedate)
WHEN 7 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [July],
sum(CASE month (SOI.fduedate)
WHEN 8 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [Aug],
sum(CASE month (SOI.fduedate)
WHEN 9 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [Sept],
sum(CASE month (SOI.fduedate)
WHEN 10 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [Oct],
sum(CASE month (SOI.fduedate)
WHEN 11 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [Nov],
sum(CASE month (SOI.fduedate)
WHEN 12 THEN (sor.forderqty * SOR.funetprice)
ELSE 0
END)
AS [Dec]
FROM SORELS SOR
JOIN SOMAST SOM
ON SOM.FSONO = SOR.FSONO
JOIN SOITEM SOI
ON SOI.FSONO = SOR.FSONO AND SOI.FINUMBER = SOR.FINUMBER
WHERE FMASTERREL = 0
AND SOM.forderdate >= CONVERT (DATETIME, '05/29/2009')
AND SOM.forderdate < CONVERT (DATETIME, '08/04/2009')
AND SOI.fduedate < CONVERT (DATETIME, '01/01/2010')
GROUP BY (SOM.[fcustno] + ' - ' + SOM.[fcompany])
Any suggestions?

Try adding the following:
ORDER BY 2, 1
to the end of your script. It seems as though you just need to sort - first by customer, then by Order / Ship

You should give a name to your 'O'/'S' column (maybe RowType). Then order by Customer, RowType.
Rob

Related

Sum of particular column with month and year with fiscal year from custom date

I have following data in my table:
uniqueId d_date amount
1 2018-02-01 100.25
2 2019-03-01 456.5
3 2018-02-01 455
4 2019-05-01 200.48
5 2018-06-01 100
6 2019-07-01 200
7 2018-12-01 6950
8 2019-02-01 60
9 2020-01-20 100
Now when I enter start date = '2018-03-12' then my fiscal year must start with march 2018 to feb 2019 and so on.
If i enter start date = '2019-05-12' then my fiscal year must start with May 2019 to April 2020
I have tried below query but it is not working properly and also it calculate past year which is 2017 I do not want any data from past year from my entered custom date. So if entered start date = '2018-03-12' then is must start calculation for 2018 and above years only. No past year.
Declare #startdate as date
Declare #monthDate as int
Declare #ownmonth as int
set #startdate = '2018-03-12'
set #monthDate = month(#startdate)
set #ownmonth = 1
select
year(dateadd(month, -#monthDate, d_date)) year,
sum(case when month(d_date) = case when #monthDate+1 > 12 then #ownmonth else #monthDate+1 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+2 > 12 then #ownmonth+1 else #monthDate+2 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+3 > 12 then #ownmonth+2 else #monthDate+3 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+4 > 12 then #ownmonth+3 else #monthDate+4 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+5 > 12 then #ownmonth+4 else #monthDate+5 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+6 > 12 then #ownmonth+5 else #monthDate+6 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+7 > 12 then #ownmonth+6 else #monthDate+7 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+8 > 12 then #ownmonth+7 else #monthDate+8 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+9 > 12 then #ownmonth+8 else #monthDate+9 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+10 > 12 then #ownmonth+9 else #monthDate+10 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+11 > 12 then #ownmonth+10 else #monthDate+11 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+12 > 12 then #ownmonth+11 else #monthDate+12 End then amount end) ,
sum(amount) total
from mytable
group by year(dateadd(month, -#monthDate, amount))
order by year
But above query does not show proper year & month wise data
Now I want output with fiscal year calculation:
Year Mar Apr May Jun July Aug Sept Oct Nov Dec Jan Feb Total
2018 - - - 100 - - - - - 6950 - 60 7110
2019 456.5 - 200.48 - 200 - - - - - 100 - 956.98
I can not use PIVOT as it is not supported in my compact SQL Server version.
How can I do this?
Your rule for a fiscal year is the year's March until the following year's February:
date | fiscal year
... | ...
2018-02-28 | 2017
2018-03-01 | 2018
... | 2018
2019-02-28 | 2018
2019-03-01 | 2019
... | ...
That means when we subtract two months from a date, we get a date the year of which is the fiscal year:
date | date - 2 months | fiscal year
... | ... | ...
2018-02-28 | 2017-12-28 | 2017
2018-03-01 | 2018-01-01 | 2018
... | ... | 2018
2019-02-28 | 2018-12-28 | 2018
2019-03-01 | 2019-01-01 | 2019
... | ... | ...
select
year(dateadd(month, -2, d_date)) as fiscal_year,
sum(case when month(d_date) = 3 then amount else 0 end) as mar,
sum(case when month(d_date) = 4 then amount else 0 end) as apr,
sum(case when month(d_date) = 5 then amount else 0 end) as may,
sum(case when month(d_date) = 6 then amount else 0 end) as jun,
sum(case when month(d_date) = 7 then amount else 0 end) as jul,
sum(case when month(d_date) = 8 then amount else 0 end) as aug,
sum(case when month(d_date) = 9 then amount else 0 end) as sep,
sum(case when month(d_date) = 10 then amount else 0 end) as oct,
sum(case when month(d_date) = 11 then amount else 0 end) as nov,
sum(case when month(d_date) = 12 then amount else 0 end) as dec,
sum(case when month(d_date) = 1 then amount else 0 end) as jan,
sum(case when month(d_date) = 2 then amount else 0 end) as feb,
sum(amount) as total
from mytable
group by year(dateadd(month, -2, d_date))
order by year(dateadd(month, -2, d_date));
If you want to limit this to the fiscal year a given date resides in, add:
where year(dateadd(month, -2, d_date)) = year(dateadd(month, -2, #given_date))
And well, if you want to limit this to the fiscal years beginning with that year, that would of course be:
where year(dateadd(month, -2, d_date)) >= year(dateadd(month, -2, #given_date))
UPDATE: You want a fiscal year to start with the first day of the month of a given date. I.e. If the given date is 1990-04-23, then a fiscal year starts with April. This changes above query only slightly, because rather than subtracting 2 months (for March), we must generalize this to subtracting one month less than the given month.
I am using a modulo operation when comparing months in order not to end up with months 13, 14, etc.
select
year(dateadd(month, - month(#startdate) + 1, d_date)) as fiscal_year,
sum(case when month(d_date) = (month(#startdate) + 0) % 12 then amount else 0 end) as first,
sum(case when month(d_date) = (month(#startdate) + 1) % 12 then amount else 0 end) as second,
sum(case when month(d_date) = (month(#startdate) + 2) % 12 then amount else 0 end) as third,
sum(case when month(d_date) = (month(#startdate) + 3) % 12 then amount else 0 end) as fourth,
sum(case when month(d_date) = (month(#startdate) + 4) % 12 then amount else 0 end) as fith,
sum(case when month(d_date) = (month(#startdate) + 5) % 12 then amount else 0 end) as sixth,
sum(case when month(d_date) = (month(#startdate) + 6) % 12 then amount else 0 end) as seventh,
sum(case when month(d_date) = (month(#startdate) + 7) % 12 then amount else 0 end) as eighth,
sum(case when month(d_date) = (month(#startdate) + 8) % 12 then amount else 0 end) as nineth,
sum(case when month(d_date) = (month(#startdate) + 9) % 12 then amount else 0 end) as tenth,
sum(case when month(d_date) = (month(#startdate) + 10) % 12 then amount else 0 end) as eleventh,
sum(case when month(d_date) = (month(#startdate) + 11) % 12 then amount else 0 end) as twelfth,
sum(amount) as total
from mytable
group by year(dateadd(month, - month(#startdate) + 1, d_date))
order by year(dateadd(month, - month(#startdate) + 1, d_date));
And again, if we want our results start from the fiscal year of the given date, we'd add:
where year(dateadd(month, - month(#startdate) + 1, d_date)) >= year(#startdate)

Rewrite the query to get output for cross years?

SELECT
sum(case
when "year" = '2016' then "svalue"
ELSE 0
END) as 'sva_2016',
sum(case
when "year" = '2017' then "svalue"
ELSE 0
END) as 'sva_2017',
sum(case
when "year" = '2018' then "svalue"
ELSE 0
END) as 'sva_2018',
sum(case
when "year" = '2019' then "svalue"
ELSE 0
END) as 'sva_2019',
sum(case
when "year" = '2016' then "ltr"
ELSE 0
END) as 'lva_2016',
sum(case
when "year" = '2017' then "ltr"
ELSE 0
END) as 'lva_2017',
sum(case
when "year" = '2018' then "ltr"
ELSE 0
END) as 'lva_2018',
sum(case
when "year" = '2019' then "ltr"
ELSE 0
END) as 'lva_2019',
'Apr 1 - Jan 31' as 'Period',
"code" as 'FACode'
FROM "FCJOIN"
WHERE "code" IN
(
SELECT "fccode"
FROM "fcdetails"
)
AND "month" between '04' and '12'
AND "year" IN ( '2016' , '2017' , '2018' , '2019' )
GROUP BY "code"
The above query gives me the correct out put for svalues and ltr for
April 2016- December 2016
April 2017- December 2017
April 2018- December 2018
April 2019- December 2019
Now I want to get the values of svalues and ltrs for the period of
April 2016- January 2017
April 2017- January 2018
April 2018- January 2019
April 2019- January 2020
You may use CAST("year" + '-' + "month" + '-01' AS DATETIME) to compare operations.
Btw. it is good example to use PIVOT operator.
Convert the year/month to a date and use date comparisons:
select f.code,
sum(case when v.dte >= '2016-04-01' and v.dte < '2017-04-01'
then f.svalue else 0
end) as svalue_2016,
. . .
sum(case when v.dte >= '2016-04-01' and v.dte < '2017-04-01'
then f.ltr else 0
end) as ltr_2016,
. . .
from fcjoin f cross apply
(values (datefromparts(f.year, f.month, 1))
) v(dte)
where f.code in (select fd.fccode from fcdetails fd)
group by code;
I removed all the double quotes, because they just complicate the query.

Call an alias in a case expression

I have this code that is to check each month to see if the person is enrolled in that month and at the end it is suppose to tell you if the person was enrolled for the whole year or not. The Annual is to check each month to see if they have a 1 from the case expression. The issue is I can't get SQL to recognize the alias names like Jan and Feb
Select SSN, FirstName, LastName,
Case (DateEnrolled > '1-1-2019' and DateEnrolled < '1-31-2019' ) then 1 else 0 as [Jan],
Case (DateEnrolled > '2-1-2019' and DateEnrolled < '2-28-2019') then 1 else 0 as [Feb],
...
Case (Jan = 1 AND Feb = 1 AND...) then 1 else 0 as [Annual]
from EmployeePerson
Try this:
with cte as
(
Select SSN, FirstName, LastName,
Case (DateEnrolled > '1-1-2019' and DateEnrolled < '1-31-2019' ) then 1 else 0 end as [Jan],
Case (DateEnrolled > '2-1-2019' and DateEnrolled < '2-28-2019') then 1 else 0 end as [Feb],
...
from EmployeePerson
)
select SSN, FirstName, LastName, [Jan], [Feb]...,[Dec],
Case (Jan = 1 AND Feb = 1 AND...AND [Dec] = 1) then 1 else 0 end as [Annual]
from cte
Try this !
SELECT SSN, FirstName, LastName,
CASE WHEN (DateEnrolled > '01-01-2019' AND DateEnrolled < '01-31-2019') THEN 'Jan',
CASE WHEN (DateEnrolled > '02-01-2019' AND DateEnrolled < '02-28-2019') THEN 'Feb'
END AS 'Annual'
FROM EmployeePerson;
I think it will be helpful.
try
select SSN, FirstName,
Case when Jan is null then 0 else 1 end as Jan,
Case when Feb is null then 0 else 1 end as Feb,
Case when Mar is null then 0 else 1 end as Mar,
Case when Apr is null then 0 else 1 end as Apr,
Case when May is null then 0 else 1 end as May,
Case when Jun is null then 0 else 1 end as Jun,
Case when Jul is null then 0 else 1 end as Jul,
Case when Aug is null then 0 else 1 end as Aug,
Case when Sep is null then 0 else 1 end as Sep,
Case when Oct is null then 0 else 1 end as Oct,
Case when Nov is null then 0 else 1 end as Nov,
Case when [Dec] is null then 0 else 1 end as [Dec],
Case when ([Jan] is not null AND [Feb] is not null AND [Mar] is not null AND
[Apr] is not null AND [May] is not null AND [Jun] is not null AND
[Jul] is not null AND [Aug] is not null AND [Sep] is not null AND
[Oct] is not null AND [Nov] is not null AND [Dec] is not null) then 1 else 0 end as Annual
from(
Select SSN, FirstName, format(DateEnrolled, 'MMM') Enrolled
from EmployeePerson)aa
pivot (max(Enrolled) for Enrolled in([Jan], [Feb], [Mar], [Apr], [May], [Jun], [Jul], [Aug], [Sep], [Oct], [Nov], [Dec])) as dtl

Re-Ordering the Months By Federal Fiscal Year

When running the following query I am trying to find a way to display the returned months by federal fiscal year instead of normal sequential value.
(ie I want to display months in the following order Oct, Nov, Dec, Jan, Feb, Mar, Apr, May Jun, Jul, Aug, Sept instead of Jan thru Dec.) Thanks
select wrkgrp,
sum (case when extract(month from reportdate) = 1 then 1 else 0 end) as January,
sum (case when extract(month from reportdate) = 2 then 1 else 0 end) as February,
sum (case when extract(month from reportdate) = 3 then 1 else 0 end) as March,
sum (case when extract(month from reportdate) = 4 then 1 else 0 end) as April,
sum (case when extract(month from reportdate) = 5 then 1 else 0 end) as May,
sum (case when extract(month from reportdate) = 6 then 1 else 0 end) as June,
sum (case when extract(month from reportdate) = 7 then 1 else 0 end) as July,
sum (case when extract(month from reportdate) = 8 then 1 else 0 end) as August,
sum (case when extract(month from reportdate) = 9 then 1 else 0 end) as September,
sum (case when extract(month from reportdate) = 10 then 1 else 0 end) as October,
sum (case when extract(month from reportdate) = 11 then 1 else 0 end) as November,
sum (case when extract(month from reportdate) = 12 then 1 else 0 end) as December,
from workorder
where reportdate between to_date ('2014-10-01 00:00:00', 'yyyy/mm/dd hh24:mi:ss')
and to_date ('2015-09-30 00:00:00', 'yyyy/mm/dd hh24:mi:ss')
and wrkgrp = 'PublicWorks'
group by 'wrkgrp;'
The fields will display in your results (horizontally) in the order you list them in your select statement. Structure your statement with Oct listed first like this:
select wrkgrp,
sum (case when extract(month from reportdate) = 10 then 1 else 0 end) as October,
sum (case when extract(month from reportdate) = 11 then 1 else 0 end) as November,
sum (case when extract(month from reportdate) = 12 then 1 else 0 end) as December,
sum (case when extract(month from reportdate) = 1 then 1 else 0 end) as January,
sum (case when extract(month from reportdate) = 2 then 1 else 0 end) as February,
sum (case when extract(month from reportdate) = 3 then 1 else 0 end) as March,
sum (case when extract(month from reportdate) = 4 then 1 else 0 end) as April,
sum (case when extract(month from reportdate) = 5 then 1 else 0 end) as May,
sum (case when extract(month from reportdate) = 6 then 1 else 0 end) as June,
sum (case when extract(month from reportdate) = 7 then 1 else 0 end) as July,
sum (case when extract(month from reportdate) = 8 then 1 else 0 end) as August,
sum (case when extract(month from reportdate) = 9 then 1 else 0 end) as September
from workorder
where reportdate between to_date ('2014-10-01 00:00:00', 'yyyy/mm/dd hh24:mi:ss') ad to_date ('2015-09-30 00:00:00', 'yyyy/mm/dd hh24:mi:ss') and
wrkgrp = 'PublicWorks'
group by 'wrkgrp;'
Add case statements in your order by clause to get the desired sort.
ORDER BY
CASE WHEN extract(month from reportdate) = 10 THEN 1
CASE WHEN extract(month from reportdate) = 11 THEN 2
ASC

Can I use pivot to add columns in the sum?

I have a query where i get the ave of a rating for different question q1-q5.
Would it possible to add the q1-q5 and divide it by the count using pivot?
I have try to make a query below:
SELECT
employeedept,YEAR_cse,csedept_name,
SUM(January) as January, SUM(February) as February,
SUM(March) as March, SUM(April) as April,
SUM(May) as May, SUM(June) as June,
SUM(July) as July, SUM(August) as August,
SUM(September) as September, SUM(October) as October,
SUM(November) as November, SUM(December) as December
FROM
(SELECT
CAST(employeedept AS INT) as dept,
ROUND(AVG(case when rating1 > 0 THEN CAST(rating1 AS FLOAT) ELSE null END), 2) as q1,
ROUND(AVG(case when rating2 > 0 THEN CAST(rating2 AS FLOAT) ELSE null END), 2) as q2,
ROUND(AVG(case when rating3 > 0 THEN CAST(rating3 AS FLOAT) ELSE null END), 2) as q3,
ROUND(AVG(case when rating4 > 0 THEN CAST(rating4 AS FLOAT) ELSE null END), 2) as q4,
ROUND(AVG(case when rating5 > 0 THEN CAST(rating5 AS FLOAT) ELSE null END), 2) as q5,
count(*) as 'totalstars',
month_cse = datename(month, approveddate),
YEAR_cse = YEAR(approveddate)
FROM
CSEReduxResponses
WHERE
execoffice_status = 1
and YEAR ([approveddate]) =2014
GROUP BY
month(approveddate), YEAR(approveddate),
DATENAME(month,approveddate), employeedept) AS r
JOIN
CSEReduxDepts d ON d.csedept_id = r.employeedept
AND YEAR_cse is NOT NULL
PIVOT( SUM(q1+q2+q3+q4+q5/totalstars)
FOR [month_cse] IN (
[January],[February],[March],[April],[May],[June],[July],[August], [September],[October],[November],[December]
)) AS pvt
Group BY employeedept,YEAR_cse,csedept_name
With this query I get this error:
Msg 102, Level 15, State 1, Line 21
Incorrect syntax near '+'.'
What I would like to do is be able to sum the q1-q5/totalstars, Would something like this be possible using pivot?
If I run the second select statement it gives me the correct results.
I think this should be your final query that you need.
I have done wrote the count function to do the average if your value is null then it will return 0 for the particular column
Lets say
rating1 = null then ISNULL(COUNT(rating1),0) = 0
rating2 = 2 then ISNULL(COUNT(rating1),0) = 1
rating3 = 3 then ISNULL(COUNT(rating1),0) = 1
so on....
Here's the query. I hope this will help you.
SELECT
employeedept,
YEAR_cse,
csedept_name,
SUM(January) as January,
SUM(February) as February,
SUM(March) as March,
SUM(April) as April,
SUM(May) as May,
SUM(June) as June,
SUM(July) as July,
SUM(August) as August,
SUM(September) as September,
SUM(October) as October,
SUM(November) as November,
SUM(December) as December
FROM
(
SELECT employeedept,
(
ROUND(AVG(case when rating1>0 THEN CAST(rating1 AS FLOAT) ELSE 0 END), 2) +
ROUND(AVG(case when rating2>0 THEN CAST(rating2 AS FLOAT) ELSE 0 END), 2) +
ROUND(AVG(case when rating3>0 THEN CAST(rating3 AS FLOAT) ELSE 0 END), 2) +
ROUND(AVG(case when rating4>0 THEN CAST(rating4 AS FLOAT) ELSE 0 END), 2) +
ROUND(AVG(case when rating5>0 THEN CAST(rating5 AS FLOAT) ELSE 0 END), 2))
/(
ISNULL(COUNT(rating1),0) +
ISNULL(COUNT(rating2),0) +
ISNULL(COUNT(rating3),0) +
ISNULL(COUNT(rating4),0)+
ISNULL(COUNT(rating5),0)) as AG,
count(*) as 'totalstars',month_cse= datename(month,approveddate),YEAR_cse =YEAR(approveddate)
FROM
CSEReduxResponses
Where
YEAR(approveddate) =2014
and execoffice_status=1
group by
employeedept,
month(approveddate),
YEAR(approveddate),
DATENAME(month,approveddate)
)AS r
JOIN CSEReduxDepts d ON d.csedept_id = r.employeedept
AND YEAR_cse is NOT NULL
PIVOT(
SUM(AG)
FOR [month_cse] IN (
[January],[February],[March],[April],[May],[June],[July],[August], [September],[October],[November],[December]
)) AS pvt
Group BY employeedept,YEAR_cse,csedept_name