Select the highest order delivered - sql

Following is my output:
MONTH STAF STAFFNAME TOTAL_ORDER_DELIVERED
===== ==== ==================== =====================
JAN S009 Theresina Ertelt 1
FEB S015 Lonna Charker 1
MAR S003 Suzi Maccari 2
MAR S010 Zacharie Witty 1
MAR S020 Abbie Gosnoll 1
MAR S017 Renee Alston 1
AUG S006 Falito Ollerton 1
AUG S017 Renee Alston 1
AUG S003 Suzi Maccari 1
OCT S003 Suzi Maccari 3
OCT S020 Abbie Gosnoll 2
What I want is:
MONTH STAF STAFFNAME TOTAL_ORDER_DELIVERED
===== ==== ==================== =====================
JAN S009 Theresina Ertelt 1
FEB S015 Lonna Charker 1
MAR S003 Suzi Maccari 2
AUG S006 Falito Ollerton 1
AUG S017 Renee Alston 1
AUG S003 Suzi Maccari 1
OCT S003 Suzi Maccari 3
I want to select the highest result based on the month but can't figure what to do. Here are my query in SQL:
SELECT TO_CHAR(TO_DATE(EXTRACT(MONTH FROM receivedDate),'mm'),'MON') AS Month,
d.staffID, staffname, count(deliveryID) AS Total_Order_Delivered
FROM delivery d, deliverystaff s
WHERE (d.staffid = s.staffid)
AND (EXTRACT(YEAR FROM receivedDate) = 2020)
GROUP BY EXTRACT(MONTH FROM d.receivedDate),d.staffid, staffname
ORDER BY EXTRACT(MONTH FROM d.receivedDate),count(deliveryID) desc;

I would suggest using RANK here:
WITH cte AS (
SELECT TO_CHAR(TO_DATE(EXTRACT(MONTH FROM receivedDate), 'mm'), 'MON') AS Month,
EXTRACT(MONTH FROM d.receivedDate) AS month_num,
d.staffID, staffname, COUNT(deliveryID) AS Total_Order_Delivered,
RANK() OVER (PARTITION BY EXTRACT(MONTH FROM d.receivedDate), d.staffid, staffname
ORDER BY COUNT(deliveryID) DESC) rnk
FROM delivery d
INNER JOIN deliverystaff s ON d.staffid = s.staffid
WHERE EXTRACT(YEAR FROM receivedDate) = 2020
GROUP BY EXTRACT(MONTH FROM d.receivedDate), d.staffid, staffname
)
SELECT Month, staffID, staffname, Total_Order_Delivered
FROM cte
WHERE rnk = 1
ORDER BY month_num;

Tim's answer is fine. However, I strongly encourage you to make some changes to the query.
First, for the where clause don't use extract(). Use direct date comparisons. Second, include the year and month in the aggregation. Then, be sure that you qualify all column references.
That allows you to do:
SELECT sd.*
FROM (SELECT TO_CHAR(d.receivedDate, 'YYYY-MON') AS Month_year,
s.staffID, s.staffname, COUNT(*) AS Total_Order_Delivered,
RANK() OVER (PARTITION BY TO_CHAR(d.receivedDate, 'YYYY-MON') ORDER BY COUNT(*) DESC) as seqnum,
MIN(d.receiveddate) as min_receiveddate
FROM deliverystaff s JOIN
delivery d
ON d.staffid = s.staffid
WHERE d.receivedDate >= DATE '2020-01-01' AND
d.receivedDate < DATE '2021-01-01'
GROUP BY TO_CHAR(d.receivedDate, 'YYYY-MON') AS Month,
s.staffID, s.staffname
) sd
WHERE seqnum = 1
ORDER BY min_receiveddate;
In addition to the above, this allows you to order the results chronologically and works if you extend the time frame to more than one year.

Related

Left Join returns NULL on matching data

I perform simple LEFT JOIN between two tables:
A:
YR QTR MTH DAY DEPT SALES
2017 2 04 2017-04-01 B xxxxxx
2017 1 03 2017-03-31 A xxxxxxxx
2017 1 03 2017-03-31 B xxxxx
2017 1 03 2017-03-30 A xxxx
Second table (B) I use to bring QTR_ALT number
YEAR MONTH QTR QTR_ALT
2016 12 4 12
2017 01 1 12
2017 02 1 12
2017 03 1 11
2017 04 2 11
Following LEFT JOIN B ON A.YR = B.YEAR AND A.QTR = B.QTR AND A.MTH=B.MONTH returns NULL for QTR_ALT for A.DAY BETWEEN '2016-12-01' AND '2017-03-31'
YR QTR QTR_ALT MTH DAY DEPT SALES
2017 2 11 04 2017-04-02 A xxxxxx
2017 2 11 04 2017-04-01 A xxxxxx
2017 2 11 04 2017-04-01 B xxxxxx
2017 1 NULL 03 2017-03-31 A xxxxxxxx
2017 1 NULL 03 2017-03-31 B xxxxx
2017 1 NULL 03 2017-03-30 A xxxx
I tried moving WHERE condition to JOIN but no luck. How is it possible these dates don't get join even though corresponding record exists in table B?
Full code:
SELECT YEAR(A.DAY) as YR,
QUARTER(A.DAY) as QTR,
B.QTR_ALT,
(REPEAT(0, 2-LENGTH(MONTH(A.DAY))) || MONTH(A.DAY)) MTH,
A.DAY,
A.DEPT,
SUM(A.VAL) as SALES
FROM A
LEFT JOIN (SELECT TO_CHAR(ADD_MONTHS(a.DT, - b.Y), 'YYYY') as YEAR,
TO_CHAR(ADD_MONTHS(a.DT, - b.Y), 'MM') as MONTH,
CEIL(TO_NUMBER(TO_CHAR(add_months(a.dt, -b.y), 'MM')) / 3) as QTR,
CEIL(b.y/3) as QTR_ALT
FROM (SELECT TRUNC(CURRENT_DATE, 'MONTH') as DT) a
CROSS JOIN (SELECT SEQ8()+1 as Y FROM TABLE(GENERATOR(ROWCOUNT => 36)) ORDER BY 1) b
ORDER BY YEAR, MONTH) B
ON QUARTER(A.DAY) = B.QTR
AND (REPEAT(0, 2-LENGTH(MONTH(A.DAY))) || MONTH(A.DAY)) = B.MONTH
WHERE (YEAR(A.DAY) = B.YEAR)
AND (A.DAY BETWEEN '2016-12-01' AND '2017-03-31')
AND A.DEPT in ('A', 'B')
GROUP BY A.DAY, YEAR(A.DAY),QUARTER(A.DAY),B.QTR_ALT,(REPEAT(0, 2-LENGTH(MONTH(A.DAY))) || MONTH(A.DAY)), DEPT
ORDER BY A.DAY DESC
CREATE TEMP TABLE A (yr number, qtr number, mth text, day date, dept text, sales number);
INSERT INTO A values (2017,2,'04','2017-04-01','B', 10),
(2017,1,'03','2017-03-31','A', 11),
(2017,1,'03','2017-03-31','B', 20),
(2017,2,'03','2017-03-30','A', 6);
WITH
sub_b AS (
SELECT
TRUNC(CURRENT_DATE, 'MONTH') AS dt,
SEQ8() AS s,
ROW_NUMBER() OVER (ORDER BY s) AS y,
ADD_MONTHS(dt, - y) as tmp_date,
TO_CHAR(tmp_date, 'YYYY') AS year,
--TO_CHAR(tmp_date, 'MM') AS month, -- NOT USED
--QUARTER(tmp_date) as QTR, -- NOT USED
CEIL(y/3) as qtr_alt -- this value seems broken
FROM TABLE(GENERATOR(ROWCOUNT => 36))
)
SELECT a.yr,
a.qtr,
b.qtr_alt,
a.mth,
a.day,
a.dept,
SUM(a.sales) AS sales
FROM a
LEFT JOIN sub_b AS b
ON a.yr = b.year AND date_trunc('month',a.day) = b.tmp_date
WHERE a.day BETWEEN '2016-12-01' AND '2017-03-31'
AND a.dept in ('A', 'B')
GROUP BY 1,2,3,4,5,6
ORDER BY a.day DESC;
seems to work as given how I read your code/intent.

Combining Dates and Ordering by Date

I have the below Query
SELECT distinct
COUNT(Status) AS [Transactions],
left(DATENAME(mm, Date_Reported), 3) AS Month,
DATENAME(yyyy, Date_Reported) AS Year
FROM [Transactions]
GROUP BY DATENAME(mm, Date_Reported), DATENAME(yyyy,Date_Reported)
ORDER BY Year, Month DESC;
My output is as below:
Transaction | Month | Year
123 | Jan | 2000
1234 | Mar | 2000
12 | Feb | 2000
How can I alter the query so I can get the month and year together like "Jan 2000" and then order it by the date so Jan 2000, Feb 2000 and Mar 2000
Thank you in advance
I think you want :
SELECT COUNT(Status) AS [Transactions], t1.MonthYear
FROM [Transactions] t
CROSS APPLY ( VALUES (CONCAT(DATENAME(mm, Date_Reported),' ',
DATENAME(yyyy, Date_Reported)),
DATEPART(mm, Date_Reported)
)
) t1 (MonthYear, Morder)
GROUP BY t1.MonthYear, t1.Morder
ORDER BY t1.Morder;

SQL NOOB - Oracle joins and Row Number

I was hoping to get some guidance on a SQL script I am trying to put together for Oracle database 11g.
I am attempting to perform a count of claims from the 'claim' table, and order them by year / month / and enterprise.
I was able to get a count of claims and order them like I would like, however I need to pull data from another table and I am having trouble combining the 'row_number' function with a join.
Here is my script so far:
SELECT TO_CHAR (SYSTEM_ENTRY_DATE, 'YYYY') YEAR,
TO_CHAR (SYSTEM_ENTRY_DATE, 'MM') MONTH,
ENTERPRISE_IID,
COUNT (*) CLAIMS
FROM (SELECT CLAIM.CLAIM_EID,
CLAIM.SYSTEM_ENTRY_DATE,
CLAIM.ENTERPRISE_IID,
ROW_NUMBER () OVER (PARTITION BY CLAIM.CLAIM_EID, CLAIM.ENTERPRISE_IID
ORDER BY CLAIM.SYSTEM_ENTRY_DATE DESC) RN
FROM CLAIM
WHERE CLAIM_IID IN (SELECT DISTINCT (CLAIM_IID)
FROM CLAIM_LINE
WHERE STATUS <> 'D')
AND CLAIM.CONTEXT = '1'
AND CLAIM.CLAIM_STATUS = 'A'
AND CLAIM.LAST_ANALYSIS_DATE IS NOT NULL)
WHERE RN = 1
GROUP ENTERPRISE_IID,
TO_CHAR (SYSTEM_ENTRY_DATE, 'YYYY'),
TO_CHAR (SYSTEM_ENTRY_DATE, 'MM');
So far all of my data is coming from the 'claim' table. This pulls the following result:
YEAR MONTH ENTERPRISE_IID CLAIMS
---- ----- -------------- ----------
2016 01 6 1
2015 08 6 3
2016 02 6 2
2015 09 6 2
2015 07 6 2
2015 09 5 22
2015 11 5 29
2015 12 5 27
2016 04 5 8
2015 07 5 29
2015 05 5 15
2015 06 5 5
2015 10 5 45
2016 03 5 54
2015 03 5 10
2016 02 5 70
2016 01 5 55
2015 08 5 32
2015 04 5 12
19 rows selected.
The enterprise_IID is the primary key on the 'enterprise' table. The 'enterprise' table also contains the 'name' attribute for each entry. I would like to join the claim and enterprise table in order to show the enterprise name for this count, and not the enterprise_IID.
As you can tell I am rather new to Oracle and SQL, and I am a bit stuck on this one. I was thinking that I should do an inner join between the two tables, but I am not quite sure how to do that when using the row_number function.
Or perhaps I am taking the wrong approach here, and someone could push me in another direction.
Here is what I tried:
SELECT TO_CHAR (SYSTEM_ENTRY_DATE, 'YYYY') YEAR,
TO_CHAR (SYSTEM_ENTRY_DATE, 'MM') MONTH,
ENTERPRISE_IID,
ENTERPRISE.NAME,
COUNT (*) CLAIMS
FROM (SELECT CLAIM.CLAIM_EID,
CLAIM.SYSTEM_ENTRY_DATE,
CLAIM.ENTERPRISE_IID,
ROW_NUMBER () OVER (PARTITION BY CLAIM.CLAIM_EID, CLAIM.ENTERPRISE_IID
ORDER BY CLAIM.SYSTEM_ENTRY_DATE DESC) RN
FROM CLAIM, enterprise
INNER JOIN ENTERPRISE
ON CLAIM.ENTERPRISE_IID = ENTERPRISE.ENTERPRISE_IID
WHERE CLAIM_IID IN (SELECT DISTINCT (CLAIM_IID)
FROM CLAIM_LINE
WHERE STATUS <> 'D')
AND CLAIM.CONTEXT = '1'
AND CLAIM.CLAIM_STATUS = 'A'
AND CLAIM.LAST_ANALYSIS_DATE IS NOT NULL)
WHERE RN = 1
GROUP BY ENTERPRISE.NAME,
ENTERPRISE_IID,
TO_CHAR (SYSTEM_ENTRY_DATE, 'YYYY'),
TO_CHAR (SYSTEM_ENTRY_DATE, 'MM');
Thank you in advance!
"Desired Output"
YEAR MONTH NAME CLAIMS
---- ----- ---- ----------
2016 01 Ent1 1
2015 08 Ent1 3
2016 02 Ent1 2
2015 09 Ent1 2
2015 07 Ent1 2
2015 09 Ent2 22
2015 11 Ent2 29
2015 12 Ent2 27
2016 04 Ent2 8
2015 07 Ent2 29
2015 05 Ent2 15
2015 06 Ent2 5
2015 10 Ent2 45
2016 03 Ent2 54
2015 03 Ent2 10
2016 02 Ent2 70
2016 01 Ent2 55
2015 08 Ent2 32
2015 04 Ent2 12
19 rows selected.
You can try this. Joins can be used when calculating row numbers with row_number function.
SELECT TO_CHAR (SYSTEM_ENTRY_DATE, 'YYYY') YEAR,
TO_CHAR (SYSTEM_ENTRY_DATE, 'MM') MONTH,
ENTERPRISE_IID,
NAME,
COUNT (*) CLAIMS
FROM (SELECT CLAIM.CLAIM_EID,
CLAIM.SYSTEM_ENTRY_DATE,
CLAIM.ENTERPRISE_IID,
ENTERPRISE.NAME,
ROW_NUMBER () OVER (PARTITION BY CLAIM.CLAIM_EID, CLAIM.ENTERPRISE_IID
ORDER BY CLAIM.SYSTEM_ENTRY_DATE DESC) RN
FROM CLAIM --, enterprise (this is not required as the table is being joined already)
INNER JOIN ENTERPRISE ON CLAIM.ENTERPRISE_IID = ENTERPRISE.ENTERPRISE_IID
INNER JOIN (SELECT DISTINCT CLAIM_IID FROM CLAIM_LINE WHERE STATUS <> 'D') CLAIM_LINE
ON CLAIM.CLAIM_IID = CLAIM_LINE.CLAIM_IID
WHERE CLAIM.CONTEXT = '1'
AND CLAIM.CLAIM_STATUS = 'A'
AND CLAIM.LAST_ANALYSIS_DATE IS NOT NULL) t
WHERE RN = 1
GROUP BY NAME, --ENTERPRISE.NAME (The alias ENTERPRISE is not accessible here.)
ENTERPRISE_IID,
TO_CHAR(SYSTEM_ENTRY_DATE, 'YYYY'),
TO_CHAR(SYSTEM_ENTRY_DATE, 'MM');
I'd write the query like this:
SELECT TO_CHAR(TRUNC(c.system_entry_date,'MM'),'YYYY') AS year
, TO_CHAR(TRUNC(c.system_entry_date,'MM'),'MM') AS month
, e.enterprise_name AS name
, COUNT(*) AS claims
FROM (
SELECT r.claim_eid
, r.enterprise_iid
, MAX(r.system_entry_date) AS system_entry_date
FROM ( SELECT DISTINCT l.claim_iid
FROM claim_line l
WHERE l.status <> 'D'
) d
JOIN claim r
ON r.claim_iid = d.claim_iid
AND r.context = '1'
AND r.claim_status = 'A'
AND r.last_analysis_date IS NOT NULL
GROUP
BY r.claim_eid
, r.enterprise_iid
) c
JOIN enterprise e
ON e.enterprise_iid = c.enterprise_iid
GROUP
BY c.enterprise_iid
, TRUNC(c.system_entry_date,'MM')
, e.enterprise_name
ORDER
BY e.enterprise_name
, TRUNC(c.system_entry_date,'MM')
A few notes:
I prefer to qualify ALL column references with the table name or short table alias, and assign aliases to all inline views.
Since the usage of ROW_NUMBER() appears to be get the "latest" system_entry_date for a claim and eliminate duplicates, I'd prefer to use a GROUP BY and a MAX() aggregate.
I prefer to use a join operation rather than the NOT IN (subquery) pattern. (Or, I would tend to use a NOT EXISTS (correlated subquery) pattern.
I don't think it matters too much if you use TO_CHAR or EXTRACT. The TO_CHAR gets you the leading zero in the month, I don't think EXTRACT(MONTH ) gets you the leading zero. I'd use whichever gets me closest to the resultset I need.Personally, I would return just a single column, either containing the year and month as one string e.g. TO_CHAR( , 'YYYYMM') or just a DATE value. It all depends what I'm going to be doing with that.
Just hypothesis to start with, because requirement of query output unclear:
SELECT
C.ENTERPRISE_IID,
E.ENTERPRISE_NAME,
extract(year from CLAIM.SYSTEM_ENTRY_DATE) SYSTEM_ENTRY_YEAR,
extract(month from CLAIM.SYSTEM_ENTRY_DATE) SYSTEM_ENTRY_MONTH,
count(distinct C.CLAIM_EID) CLAIM_COUNT
FROM
CLAIM C,
ENTERPRISE E
WHERE
C.CLAIM_IID IN (
SELECT DISTINCT (CLAIM_IID)
FROM CLAIM_LINE
WHERE STATUS <> 'D'
)
AND C.CONTEXT = '1'
AND C.CLAIM_STATUS = 'A'
AND C.LAST_ANALYSIS_DATE IS NOT NULL
AND E.ENTERPRISE_IID = C.ENTERPRISE_IID
GROUP BY
C.ENTERPRISE_IID,
E.ENTERPRISE_NAME,
extract(year from CLAIM.SYSTEM_ENTRY_DATE),
extract(month from CLAIM.SYSTEM_ENTRY_DATE)
ORDER BY
extract(year from CLAIM.SYSTEM_ENTRY_DATE),
extract(month from CLAIM.SYSTEM_ENTRY_DATE),
E.ENTERPRISE_NAME

Sql query for the following situation

Tom loves sports. Every month he takes rest for a while and plays his favorite sport. He changes the game during the month and its change history is shown in table.
Challenge: What is the first and last favorite sport played by Tom?
Tom Favourite Sports
----------------------
Month PreviousSport CurrentSport
JAN REST CRICKET
JAN CRICKET RUGBY
JAN RUGBY VOLLEYBALL
JAN VOLLEYBALL FOOTBALL
JAN FOOTBALL TENNIS
JAN TENNIS RUGBY
FEB REST KAYAKING
FEB KAYAKING SNOWBOARDING
FEB SNOWBOARDING SKATING
FEB SKATING RAFTING
FEB RAFTING KAYAKING
MAR REST RACING
MAR RACING GLIDING
MAR GLIDING SKYDIVING
And the output should be
Month FirstSport LastSport
JAN CRICKET RUGBY
FEB KAYAKING KAYAKING
MAR RACING SKYDIVING
CHANGE : Slight modification to the source table
MTH PREVIOUS_SPORT CURRENT_SPORT
JAN VOLLEYBALL FOOTBALL
FEB REST KAYAKING
MAR REST RACING
JAN CRICKET RUGBY
FEB SNOWBOARDING SKATING
MAR RACING GLIDING
JAN RUGBY VOLLEYBALL
FEB SKATING RAFTING
MAR GLIDING SKYDIVING
JAN FOOTBALL TENNIS
FEB RAFTING KAYAKING
JAN TENNIS RUGBY
JAN REST CRICKET
Now how do I get the previous output?
Thanks in advance.
I just have considered ID column for Table, we can avoid it & convert Jan/Feb/March as Month Numbers & go ahead without ID column. But for quick reply, This is it !!!
Select Main.[Month],F.CurrentSport,L.CurrentSport from
(
Select a.[Month],min(r) fSport ,max(r) lSport from
(select * ,ROW_NUMBER() over (Partition by Month order by ID) as R
from Tom
)a
group by a.[Month]
)as Main
inner join
(
select *, ROW_NUMBER() over (Partition by Month order by ID) as R
from Tom
)as F on F.R = Main.fSport and f.[Month] = Main.[Month]
inner join
(
select *, ROW_NUMBER() over (Partition by Month order by ID) as R
from Tom
)as L on L.R = Main.lSport and L.[Month] = Main.[Month]
order by F.ID
See Fiddle DEMO HERE
One more variant, avoiding ROW_Number multiple times & using CTE. I think this should be faster than previous.
;With CTE as
(
select ID,[Month] as M,CurrentSport as Sport
, ROW_NUMBER() over (Partition by Month order by ID) as R
from Tom
), CTE1 as
(
Select M, Min(R) as FS ,Max(R) as LS from CTE
group by M
)
Select CTE1.M,F.Sport as First,L.Sport as Last from CTE1
inner join CTE as F on F.R = CTE1.FS and F.M = CTE1.M
inner join CTE as L on L.R = CTE1.LS and L.M = CTE1.M
order by L.ID asc
See DEMO HERE
I don't think we need the ID column as such. We can work with RowNumber.
So it should be coming up like this :
SELECT Mintmp.mnth,
Mintmp.currentsport AS FirstSport,
MaxTmp.currentsport AS CurrentSport
FROM (SELECT Row_number()
OVER(
partition BY mnth
ORDER BY mnth) AS RowNum,
*
FROM #T1) MinTmp
INNER JOIN (SELECT Min(rownum) AS MinRow,
mnth,
Max(rownum) AS MaxRow
FROM (SELECT Row_number()
OVER(
partition BY mnth
ORDER BY mnth) AS RowNum,
*
FROM #T1) tmp
GROUP BY mnth) grpTable
ON grpTable.minrow = MinTmp.rownum
AND grpTable.mnth = MinTmp.mnth
INNER JOIN (SELECT Row_number()
OVER(
partition BY mnth
ORDER BY mnth) AS RowNum,
*
FROM #T1) MaxTmp
ON Maxtmp.rownum = grpTable.maxrow
AND Maxtmp.mnth = grpTable.mnth

show column value in 'previous row' and in a new column

I have a table with four columns; Plant_Id, Year, Month and MR. I would like to be able to calculate the Range (month 2 month difference) of MR.
A sample of the table (MaintenanceRatebepaen is the table name) looks like this:
Plant_ID Year Month MR
CCAR 2009 1 0,706452
CCAR 2009 2 0,625899
CCAR 2009 3 0,636678
CCAR 2009 4 0,736544
CCAR 2009 5 0,552023
CCAR 2009 6 0,418338
CCAR 2009 7 0,502732
CCAR 2009 8 0,64526
CCAR 2009 9 0,743333
CCAR 2009 10 0,555556
CCAR 2009 11 0,297561
CCAR 2009 12 0,338608
CCAR 2010 1 0,380783
Etc.
I'm not sure this is of interest, but Plant_id can have 25 different values, years from 2008 - 2012, months 1-12, MR is a calculated value.
The Query looks like this:
SELECT Plant_Id, Jaar, Maand
, (SUM(Compl) + 0.000) / SUM(Total) AS MR
FROM (
SELECT Plant_Id, Jaar, Late, EarlyJobs, OnTimeJobs, Maand
, SUM(EarlyJobs + OnTimeJobs) AS Compl
, SUM(EarlyJobs) + SUM(Late) + SUM(OnTimeJobs) AS Total
FROM MaintenanceRatebepaen AS MaintenanceRatebepaen_1
GROUP BY Plant_Id, Jaar, Maand, Late, OnTimeJobs, EarlyJobs
) AS MaintenanceRatebepaen
WHERE (Jaar >= 2009) AND (Jaar <= 2011) AND (Plant_Id = 'CCAR')
GROUP BY Jaar, Plant_Id, Maand
ORDER BY Plant_Id, Jaar, Maand
I'm new to SQL, I managed to get the above from books and google searches. But I can't get the Range calculated, any help is greatly appreciated!
Did you just want month by month differences?
Data
declare #data table (PlantId nvarchar(5), [Year] nvarchar(4), [Month] int, MR decimal(10,10))
INSERT #data VALUES
('CCAR','2009','1','0.706452'),('CCAR','2009','2','0.625899'),('CCAR','2009','3','0.636678'),('CCAR','2009','4','0.736544'),('CCAR','2009','5','0.552023'),('CCAR','2009','6','0.418338'),('CCAR','2009','7','0.502732'),('CCAR','2009','8','0.64526'),('CCAR','2009','9','0.743333'),('CCAR','2009','10','0.555556'),('CCAR','2009','11','0.297561'),('CCAR','2009','12','0.338608'),('CCAR','2010','1','0.380783')
Query
;with cte as (
SELECT *, ROW_NUMBER() OVER (ORDER BY Year DESC, Month DESC) AS RowNumber FROM #data
)
select d1.PlantId
, d1.Year
, d1.Month
, d1.MR
, d1.MR-d2.MR AS [ChangeMRFromPreviousMonth]
from cte d1
LEFT OUTER JOIN cte d2
on d2.RowNumber = (d1.RowNumber+1)
order by d1.RowNumber DESC
Results:
PlantId Year Month MR ChangeMRFromPreviousMonth
------- ---- ----------- --------------------------------------- ---------------------------------------
CCAR 2009 1 0.7064520000 NULL
CCAR 2009 2 0.6258990000 -0.0805530000
CCAR 2009 3 0.6366780000 0.0107790000
CCAR 2009 4 0.7365440000 0.0998660000
CCAR 2009 5 0.5520230000 -0.1845210000
CCAR 2009 6 0.4183380000 -0.1336850000
CCAR 2009 7 0.5027320000 0.0843940000
CCAR 2009 8 0.6452600000 0.1425280000
CCAR 2009 9 0.7433330000 0.0980730000
CCAR 2009 10 0.5555560000 -0.1877770000
CCAR 2009 11 0.2975610000 -0.2579950000
CCAR 2009 12 0.3386080000 0.0410470000
CCAR 2010 1 0.3807830000 0.0421750000
Is that what you needed? Your query contains alot of extra columns, so I don't know if you want that including?
* Edit *
In response to your comments, you need to put your query inside the CTE, with the additional RowNumber column. d1 and d2 are just aliases of that CTE. I think this should do it:
;with cte as (
SELECT Plant_Id, Jaar, Maand
, (SUM(Compl) + 0.000) / SUM(Total) AS MR
, ROW_NUMBER() OVER (ORDER BY Jaar DESC, Maand DESC) AS RowNumber
FROM (
SELECT Plant_Id, Jaar, Late, EarlyJobs, OnTimeJobs, Maand
, SUM(EarlyJobs + OnTimeJobs) AS Compl
, SUM(EarlyJobs) + SUM(Late) + SUM(OnTimeJobs) AS Total
FROM MaintenanceRatebepaen AS MaintenanceRatebepaen_1
GROUP BY Plant_Id, Jaar, Maand, Late, OnTimeJobs, EarlyJobs
) AS MaintenanceRatebepaen
WHERE (Jaar >= 2009) AND (Jaar <= 2011) AND (Plant_Id = 'CCAR')
GROUP BY Jaar, Plant_Id, Maand
ORDER BY Plant_Id, Jaar, Maand
)
select d1.PlantId
, d1.Jaar
, d1.Maand
, d1.MR
, d1.MR-d2.MR AS [ChangeMRFromPreviousMonth]
from cte d1
LEFT OUTER JOIN cte d2
on d2.RowNumber = (d1.RowNumber+1)
order by d1.RowNumber DESC