Most recent rows with column from previous most recent rows - sql

I have fetched all the rows with most recent rows for every orderID with this VIEW.But I also need another Column "PreviousStatusID" which will store the previous most recent row's StatusID.. Is it possible to implement ? Please Help.
The View :
ALTER VIEW [dbo].[VW_PatientOrderByMaxTimeAddedProc]
AS
SELECT
t.ID,
t.ExamDate,
t.ArrivalTime,
t.Activity,
t.PatientFirstName,
t.PatientMiddleName,
t.PatientLastName,
t.DOB,
t.[Order],
t.ActualExamTimeIn,
t.ActualExamTimeOut,
t.ActualScannerID,
t.ActualExamDate,
t.ActualCustomer,
t.ActualPatientFirstName,
t.ActualPatientLastName,
t.ActualDOB,
t.InsuranceCoID,
t.InsuranceID,
t.StartedInPreAuth,
t.DateReceived,
t.TimeReceived,
FDGPatientOrder,
StatusID,
TimeAdded ,
Notes,
cntID,
empID,
Isotope,
Weight,
Diabetic,
Indication,
[Procedure],
InjectionTime,
PhysicianFirstName ,
PhysicianText,
IndicationDescription
FROM
dbo.smsFDGPatientOrder t
INNER JOIN
dbo.smsFDGPatientOrderStatus ON t.ID = FDGPatientOrder
INNER JOIN
(
SELECT
smsFDGPatientOrder.ID,
MAX(TimeAdded) AS MAX_TIME
FROM
dbo.smsFDGPatientOrder AS smsFDGPatientOrder
INNER JOIN
dbo.smsFDGPatientOrderStatus ON smsFDGPatientOrder.ID = FDGPatientOrder
GROUP BY
smsFDGPatientOrder.ID
)
a ON a.ID = t.ID and a.MAX_TIME = TimeAdded

What version of SQL? In 2012+, you can use the LAG window function to make this not too bad.
SELECT WindowedView.FDGPatientOrder
FROM (
SELECT FDGPatientOrder,
StatusId,
TimeAdded,
MAX(TimeAdded) OVER (PARTITION BY FDGPatientOrder) AS MostRecentTimeAdded,
LAG(StatusId, 1, NULL) OVER (PARTITION BY FDGPatientOrder ORDER BY TimeAdded DESC) AS PrevStatusId
FROM PatientOrders
) WindowedView
WHERE WindowedView.StatusId = 3
AND WindowedView.PrevStatusId IN (4, 9, 10, 20, 21, 22)
AND WindowedView.TimeAdded = WindowedView.MostRecentTimeAdded

Related

how optimize execution time of query using indexes

how I can optimize execution time of this query using indexes?
Do you know another method?
SELECT [FILE_NAME],
[RUN_ID],
[APPIANID],
[DOSSIERID],
[funnelid],
[codice_fiscale],
[data_apertura],
REPLACE([data_chiusura], 'NULL', '') AS [data_chiusura],
[codice_lavorazione],
[desc_lavorazione],
sd.[stato],
[data_ultima_modifica],
[operatore],
[datastato],
min_data_apertura,
email,
cellulare,
RANK() OVER (PARTITION BY dossierid ORDER BY [data_ultima_modifica] DESC) AS last_status_dossier,
RANK() OVER (PARTITION BY appianid ORDER BY [data_ultima_modifica] DESC) AS last_status_appianid,
RANK() OVER (PARTITION BY dossierid ORDER BY [data_apertura] ASC) AS first_status_dossier,
RANK() OVER (PARTITION BY appianid ORDER BY [data_apertura] ASC) AS first_status_appianid,
COALESCE(source, 'NA') AS Source,
COALESCE(Gruppo, sd.codice_lavorazione) AS Gruppo,
COALESCE(ESITO_LAVORAZIONE, 'NA') AS Esito_lavorazione
FROM [Fibra].[SD_Full_TEST1] sd
LEFT JOIN [Fibra].[SD_Source] s ON sd.codice_lavorazione = s.cod_lavorazione
LEFT JOIN (SELECT [DOSSIERID] AS dossier,
MIN(data_apertura) AS min_data_apertura
FROM [Fibra].[SD_Full_TEST1]
GROUP BY [DOSSIERID]) b ON sd.DOSSIERID = b.DOSSIER
LEFT JOIN [Fibra].[SD_Macro_Raggruppamenti] mr ON sd.codice_lavorazione = mr.codice_motivazione
LEFT JOIN [Fibra].[SD_Esito_Lavorazione] el ON sd.stato = el.STATO
WHERE CONVERT(datetime, [data_apertura]) >= CAST('02/27/2021' AS date)
AND COALESCE(codice_lavorazione, 'NA') != 'TIMEOUT';
I tried to create nonclustered index for dossierid, appianid, data_apertura and data_ultima_modifica but it is not working.

SQL - ROW_NUMBER that is used in a multi-condition LEFT JOIN

Two tables store different properties for each product: CTI_ROUTING_VIEW and ORD_MACH_OPS
They are both organized by SPEC_NO > MACH_SEQ_NO but the format of the Sequence number is different for each table so it can't be used for a JOIN. ORCH_MACH_OPS has MACHINE and PASS_NO, meaning if a product goes through the same machine twice, the row with the higher SEQ_NO will be PASS_NO 2, 3, etc. CTI_ROUTING_VIEW does not offer PASS_NO, but I can achieve the desired result with:
SELECT TOP (1000) [SPEC_NO]
,[SPEC_PART_NO]
,[MACH_NO]
,[MACH_SEQ_NO]
,[BLANK_WID]
,[BLANK_LEN]
,[NO_OUT_WID]
,[NO_OUT_LEN]
,[SU_MINUTES]
,[RUN_SPEED]
,[NO_COLORS]
,[PRINTDIEID]
,[CUTDIEID]
,ROW_NUMBER() OVER (PARTITION BY MACH_NO ORDER BY MACH_SEQ_NO) as PASS_NO
FROM [CREATIVE].[dbo].[CTI_ROUTING_VIEW]
I would think that I could use this artificial PASS_NO as a JOIN condition, but I can't seem to get it to come through. This is my first time using ROW_NUMBER() so I'm just wondering if I'm doing something wrong in the JOIN syntax.
SELECT rOrd.[SPEC_NO]
,rOrd.[MACH_SEQ_NO]
,rOrd.[WAS_REROUTED]
,rOrd.[NO_OUT]
,rOrd.[PART_COMP_FLG]
,rOrd.[SCHED_START]
,rOrd.[SCHED_STOP]
,rOrd.[MACH_REROUTE_FLG]
,rOrd.[MACH_DESCR]
,rOrd.REPLACED_MACH_NO
,rOrd.MACH_NO
,rOrd.PASS_NO
,rWip.MAX_TRX_DATETIME
,ISNULL(rWip.NET_FG_SUM*rOrd.NO_OUT,0) as NET_FG_SUM
,CASE
WHEN rCti.BLANK_WID IS NULL then 'N//A'
ELSE CONCAT(rCti.BLANK_WID, ' X ', rCti.BLANK_LEN)
END AS SIZE
,ISNULL(rCti.PRINTDIEID,'N//A') as PRINTDIEID
,ISNULL(rCti.CUTDIEID, 'N//A') as CUTDIEID
,rStyle.DESCR as STYLE
,ISNULL(rCti.NO_COLORS, 0) as NO_COLORS
,CAST(CONCAT(rOrd.ORDER_NO,'-',rOrd.ORDER_PART_NO) as varchar) as ORD_MACH_KEY
FROM [CREATIVE].[dbo].[ORD_MACH_OPS] as rOrd
LEFT JOIN (SELECT DISTINCT
[SPEC_NO]
,[SPEC_PART_NO]
,[MACH_NO]
,MACH_SEQ_NO
,[BLANK_WID]
,[BLANK_LEN]
,[NO_COLORS]
,[PRINTDIEID]
,[CUTDIEID]
,ROW_NUMBER() OVER (PARTITION BY MACH_NO ORDER BY MACH_SEQ_NO) as PASS_NO
FROM [CREATIVE].[dbo].[CTI_ROUTING_VIEW]) as rCti
ON rCti.SPEC_NO = rOrd.SPEC_NO
and rCti.MACH_NO =
CASE
WHEN rOrd.REPLACED_MACH_NO is null then rOrd.MACH_NO
ELSE rOrd.REPLACED_MACH_NO
END
and rCti.PASS_NO = rOrd.PASS_NO
LEFT JOIN INVENTORY_ITEM_TAB as rTab
ON rTab.SPEC_NO = rOrd.SPEC_NO
LEFT JOIN STYLE_DESCRIPTION as rStyle
ON rStyle.DESCR_CD = rTab.STYLE_CD
LEFT JOIN (
SELECT
JOB_NUMBER
,FORM_NO
,TRX_ORIG_MACH_NO
,PASS_NO
,SUM(GROSS_FG_QTY-WASTE_QTY) as NET_FG_SUM
,MAX(TRX_DATETIME) as MAX_TRX_DATETIME
FROM WIP_MACH_OPS
WHERE GROSS_FG_QTY <> 0
GROUP BY JOB_NUMBER, FORM_NO, TRX_ORIG_MACH_NO, PASS_NO) as rWip
ON rWip.JOB_NUMBER = rOrd.ORDER_NO
and rWip.FORM_NO = rOrd.ORDER_PART_NO
and rWip.TRX_ORIG_MACH_NO = rOrd.MACH_NO
and rWip.PASS_NO = rOrd.PASS_NO
WHERE rOrd.SCHED_START > DATEADD(DAY, -20, GETDATE())
I fixed it by adding a second partition.
ROW_NUMBER() OVER (PARTITION BY SPEC_NO, MACH_NO ORDER BY MACH_SEQ_NO) as PASS_NO

How to select a single row for each unique ID

SQL novice here learning on the job, still a greenhorn. I have a problem I don't know how to overcome. Using IBM Netezza and Aginity Workbench.
My current output will try to return one row per case number based on when a task was created. It will only keep the row with the newest task. This gets me about 85% of the way there. The issue is that sometimes multiple tasks have a create day of the same day.
I would like to incorporate Task Followup Date to only keep the newest row if there are multiple rows with the same Case Number. I posted an example of what my current code outputs and what i would like it to output.
Current code
SELECT
A.PS_CASE_ID AS Case_Number
,D.CASE_TASK_TYPE_NM AS Task
,C.TASK_CRTE_TMS
,C.TASK_FLWUP_DT AS Task_Followup_Date
FROM VW_CC_CASE A
INNER JOIN VW_CASE_TASK C ON (A.CASE_ID = C.CASE_ID)
INNER JOIN VW_CASE_TASK_TYPE D ON (C.CASE_TASK_TYPE_ID = D.CASE_TASK_TYPE_ID)
INNER JOIN ADMIN.VW_RSN_CTGY B ON (A.RSN_CTGY_ID = B.RSN_CTGY_ID)
WHERE
(A.PS_Z_SPSR_ID LIKE '%EFT' OR A.PS_Z_SPSR_ID LIKE '%CRDT')
AND CAST(A.CASE_CRTE_TMS AS DATE) >= '2020-01-01'
AND B.RSN_CTGY_NM = 'Chargeback Initiation'
AND CAST(C.TASK_CRTE_TMS AS DATE) = (SELECT MAX(CAST(C2.TASK_CRTE_TMS AS DATE)) from VW_CASE_TASK C2 WHERE C2.CASE_ID = C.CASE_ID)
GROUP BY
A.PS_CASE_ID
,D.CASE_TASK_TYPE_NM
,C.TASK_CRTE_TMS
,C.TASK_FLWUP_DT
Current output
Desired output
You could use ROW_NUMBER here:
WITH cte AS (
SELECT DISTINCT A.PS_CASE_ID AS Case_Number, D.CASE_TASK_TYPE_NM AS Task,
C.TASK_CRTE_TMS, C.TASK_FLWUP_DT AS Task_Followup_Date,
ROW_NUMBER() OVER (PARTITION BY A.PS_CASE_ID ORDER BY C.TASK_FLWUP_DT DESC) rn
FROM VW_CC_CASE A
INNER JOIN VW_CASE_TASK C ON A.CASE_ID = C.CASE_ID
INNER JOIN VW_CASE_TASK_TYPE D ON C.CASE_TASK_TYPE_ID = D.CASE_TASK_TYPE_ID
INNER JOIN ADMIN.VW_RSN_CTGY B ON A.RSN_CTGY_ID = B.RSN_CTGY_ID
WHERE (A.PS_Z_SPSR_ID LIKE '%EFT' OR A.PS_Z_SPSR_ID LIKE '%CRDT') AND
CAST(A.CASE_CRTE_TMS AS DATE) >= '2020-01-01' AND
B.RSN_CTGY_NM = 'Chargeback Initiation' AND
CAST(C.TASK_CRTE_TMS AS DATE) = (SELECT MAX(CAST(C2.TASK_CRTE_TMS AS DATE))
FROM VW_CASE_TASK C2
WHERE C2.CASE_ID = C.CASE_ID)
)
SELECT
Case_Number,
Task,
TASK_CRTE_TMS,
Task_Followup_Date
FROM cte
WHERE rn = 1;
One method used window functions:
with cte as (
< your query here >
)
select x.*
from (select cte.*,
row_number() over (partition by case_number, Task_Followup_Date
order by TASK_CRTE_TMS asc
) as seqnum
from cte
) x
where seqnum = 1;

Use of MAX function in SQL query to filter data

The code below joins two tables and I need to extract only the latest date per account, though it holds multiple accounts and history records. I wanted to use the MAX function, but not sure how to incorporate it for this case. I am using My SQL server.
Appreciate any help !
select
PROP.FileName,PROP.InsName, PROP.Status,
PROP.FileTime, PROP.SubmissionNo, PROP.PolNo,
PROP.EffDate,PROP.ExpDate, PROP.Region,
PROP.Underwriter, PROP_DATA.Data , PROP_DATA.Label
from
Property.dbo.PROP
inner join
Property.dbo.PROP_DATA on Property.dbo.PROP.FileID = Actuarial.dbo.PROP_DATA.FileID
where
(PROP_DATA.Label in ('Occupancy' , 'OccupancyTIV'))
and (PROP.EffDate >= '42278' and PROP.EffDate <= '42643')
and (PROP.Status = 'Bound')
and (Prop.FileTime = Max(Prop.FileTime))
order by
PROP.EffDate DESC
Assuming your DBMS supports windowing functions and the with clause, a max windowing function would work:
with all_data as (
select
PROP.FileName,PROP.InsName, PROP.Status,
PROP.FileTime, PROP.SubmissionNo, PROP.PolNo,
PROP.EffDate,PROP.ExpDate, PROP.Region,
PROP.Underwriter, PROP_DATA.Data , PROP_DATA.Label,
max (PROP.EffDate) over (partition by PROP.PolNo) as max_date
from Actuarial.dbo.PROP
inner join Actuarial.dbo.PROP_DATA
on Actuarial.dbo.PROP.FileID = Actuarial.dbo.PROP_DATA.FileID
where (PROP_DATA.Label in ('Occupancy' , 'OccupancyTIV'))
and (PROP.EffDate >= '42278' and PROP.EffDate <= '42643')
and (PROP.Status = 'Bound')
and (Prop.FileTime = Max(Prop.FileTime))
)
select
FileName, InsName, Status, FileTime, SubmissionNo,
PolNo, EffDate, ExpDate, Region, UnderWriter, Data, Label
from all_data
where EffDate = max_date
ORDER BY EffDate DESC
This also presupposes than any given account would not have two records on the same EffDate. If that's the case, and there is no other objective means to determine the latest account, you could also use row_numer to pick a somewhat arbitrary record in the case of a tie.
Using straight SQL, you can use a self-join in a subquery in your where clause to eliminate values smaller than the max, or smaller than the top n largest, and so on. Just set the number in <= 1 to the number of top values you want per group.
Something like the following might do the trick, for example:
select
p.FileName
, p.InsName
, p.Status
, p.FileTime
, p.SubmissionNo
, p.PolNo
, p.EffDate
, p.ExpDate
, p.Region
, p.Underwriter
, pd.Data
, pd.Label
from Actuarial.dbo.PROP p
inner join Actuarial.dbo.PROP_DATA pd
on p.FileID = pd.FileID
where (
select count(*)
from Actuarial.dbo.PROP p2
where p2.FileID = p.FileID
and p2.EffDate <= p.EffDate
) <= 1
and (
pd.Label in ('Occupancy' , 'OccupancyTIV')
and p.Status = 'Bound'
)
ORDER BY p.EffDate DESC
Have a look at this stackoverflow question for a full working example.
Not tested
with temp1 as
(
select foo
from bar
whre xy = MAX(xy)
)
select PROP.FileName,PROP.InsName, PROP.Status,
PROP.FileTime, PROP.SubmissionNo, PROP.PolNo,
PROP.EffDate,PROP.ExpDate, PROP.Region,
PROP.Underwriter, PROP_DATA.Data , PROP_DATA.Label
from Actuarial.dbo.PROP
inner join temp1 t
on Actuarial.dbo.PROP.FileID = t.dbo.PROP_DATA.FileID
ORDER BY PROP.EffDate DESC

Semi-Tricky SQL Query

I am trying to write a query for SQL Server 2005 but I can't figure out how to do it. I have a table with the following fields:
MessageID int
CategoryID int
Priority tinyint
MessageText NVARCHAR(MAX)
I need a query that will return * for each row that has the highest priority within a Category. For example, if I had the following data:
MessageID, CategoryID, Priority, MessageText
1, 100, 1, Error #1234 occurred
2, 100, 2, Error #243 occurred
3, 100, 3, Error #976 occurred
4, 200, 4, Error #194 occurred
5, 200, 1, Error #736 occurred
6, 300, 3, Error #54 occurred
7, 300, 2, Error #888 occurred
then the result would be:
MessageID, CategoryID, Priority, MessageText
3, 100, 3, Error #976 occurred
4, 200, 4, Error #194 occurred
6, 300, 3, Error #54 occurred
Notice that it returns one row per category, and that it is the row which had the highest priority for that Category.
Can anyone tell me how I can write this query?
Verified:
SELECT
highest_priority_messages.*
FROM
(
SELECT
m.MessageID
, m.CategoryID
, m.Priority
, m.MessageText
, Rank() OVER
(PARTITION BY m.CategoryID ORDER BY m.Priority DESC) AS p_rank
FROM [Message] m
GROUP BY
m.CategoryID
, m.Priority
, m.MessageID
, m.MessageText
) highest_priority_messages
WHERE
p_rank = 1
I believe that this should work, table name assumed as Messages
SELECT
M.MessageId,
M.CategoryId,
M.Priority,
M.MessageText
FROM
(
SELECT
CategoryId,
MAX(Priority) AS Priority
FROM Messages
GROUP BY CategoryId
) AS MaxValues
INNER JOIN Messages M
ON (MaxValues.CategoryId = M.CategoryId
AND MaxValues.Priority = M.Priority)
NOTE
The only "gotcha" in this method is that if you have more than one max priority...
If you'd like to do it without all of the subqueries:
SELECT
MessageID,
CategoryID,
Priority,
MessageText
FROM
dbo.Messages M1
LEFT OUTER JOIN dbo.Messages M2 ON
M2.CategoryID = M1.CategoryID AND
M2.Priority > M1.Priority
WHERE
M2.MessageID IS NULL
You might have to adjust the query depending on how you want to handle ties. You didn't have any such examples, so I wasn't sure.
select distinct query1.* from
(select categoryId,msgText,max(priorityId) as MAX_PRIORITY
from message
group by categoryId,msgText
order by categoryId
) query1,
(select categoryId,max(priorityId) as MAX_PRIORITY
from message
group by categoryId
order by categoryId
) query2
where query1.MAX_PRIORITY = query2.MAX_PRIORITY
order by query1.categoryId
SELECT
Messages.MessageID
, Messages.CategoryID
, Messages.Priority
, Messages. MessageText
FROM
Messages
INNER JOIN
(
SELECT
CategoryID
, MAX(Priority) AS Priority
FROM
Messages
GROUP BY
CategoryID
) AS MaxResults
ON
(
Messages.CategoryID = MaxResults.CategoryID
AND
Messages.Priority = MaxResults.Priority
)
It looks like this is basically the same answer given above... with the same Caveat.
Although this one will work right off the bat.
This is shorter and easier to read (imo).
select ms.*
from
messages ms
,(
select ms1.categoryid, max(ms1.priority) as max_priority
from messages ms1
group by ms1.categoryid
) tmp
where ms.categoryid = tmp.categoryid
and ms.priority = tmp.max_priority;
SELECT DISTINCT CategoryId,PS.Priority,MessageID,MessageText
FROM Priority_Scene PS
JOIN (SELECT MAX(Priority) AS Priority FROM Priority_Scene GROUP BY CategoryId) A
ON A.Priority = PS.Priority
I'm not quite high enough rank (yet) to post a comment, so I'd like to add to cfeduke's solution:
SELECT
highest_priority_messages.*
FROM
(
SELECT
m.MessageID
, m.CategoryID
, m.Priority
, m.MessageText
, Rank() OVER
(PARTITION BY m.CategoryID ORDER BY m.Priority DESC, m.MessageID DESC) AS p_rank
FROM [Message] m
GROUP BY
m.CategoryID
, m.Priority
, m.MessageID
, m.MessageText
) highest_priority_messages
WHERE
p_rank = 1
If you add another CategoryID 100 Message with Priority 3, the original solution would bring back 2 rows, by adding another order condition we eliminate the chance of two items ranking the same.
Here's a copy of the row I inserted to test this.
insert into [Message] (MessageID, CategoryID, Priority, MessageText)
select 8, 100, 3, 'Error #976-2 occurred'