I have a stored procedure with a couple of input parameters
Input parameters:
@UnitID = 13001,
@WOID = 731000037,732000049
Result set:
AuxTable
is not the final intended table, it's just being displayed for debugging/troubleshooting.
MsgLinkId | MyRowId | WO_ID | SourceUnitName | MaterialName | BatchID | UnitofMeasure | Segment1 | Segment2 | Segment3 | Segment4 | Segment5 | Amount | StartDate | EndDate |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
5 | 1 | 731000037 | B1S01C03 | RAW MILK | 0 | KGM | B1S01W32 | NONE | NONE | NONE | NONE | 13391.7524414063 | 2022-01-01 14:22:25.773 | 2022-01-01 14:24:25.980 |
5 | 2 | 731000037 | B1S01C03 | RAW MILK | 0 | KGM | B1S01W32 | NONE | NONE | NONE | NONE | 13391.7524414063 | 2022-01-01 14:22:25.773 | 2022-01-01 14:26:26.187 |
5 | 3 | 731000037 | B1S01C03 | RAW MILK | 0 | KGM | B1S01W32 | NONE | NONE | NONE | NONE | 13391.7524414063 | 2022-01-01 14:22:25.773 | 2022-01-01 14:28:26.397 |
7 | 1 | 732000049 | B1S01C03 | RAW MILK | 0 | KGM | B1S01W32 | NONE | NONE | NONE | NONE | 31993.4200439453 | 2022-01-02 17:12:43.550 | 2022-01-02 17:14:43.757 |
7 | 2 | 732000049 | B1S01C03 | RAW MILK | 0 | KGM | B1S01W32 | NONE | NONE | NONE | NONE | 31993.4200439453 | 2022-01-02 17:12:43.550 | 2022-01-02 17:16:43.967 |
7 | 3 | 732000049 | B1S01C03 | RAW MILK | 0 | KGM | B1S01W32 | NONE | NONE | NONE | NONE | 31993.4200439453 | 2022-01-02 17:12:43.550 | 2022-01-02 17:18:44.177 |
3 | 1 | 732000049 | B1S01C04 | RAW MILK | 0 | KGM | B1S01W32 | NONE | NONE | NONE | NONE | 57417.6939544678 | 2022-01-02 15:48:17.530 | 2022-01-02 15:50:17.737 |
3 | 2 | 732000049 | B1S01C04 | RAW MILK | 0 | KGM | B1S01W32 | NONE | NONE | NONE | NONE | 57417.6939544678 | 2022-01-02 15:48:17.530 | 2022-01-02 15:52:17.947 |
3 | 3 | 732000049 | B1S01C04 | RAW MILK | 0 | KGM | B1S01W32 | NONE | NONE | NONE | NONE | 57417.6939544678 | 2022-01-02 15:48:17.530 | 2022-01-02 15:54:18.157 |
FinalTable
:
Unit_WO | SourceUnitName | MaterialName | BatchID | UnitofMeasure | Segment1 | Segment2 | Segment3 | Segment4 | Segment5 | Amount | StartDate | EndDate |
---|---|---|---|---|---|---|---|---|---|---|---|---|
731000037 | B1S01C03 | RAW MILK | 0 | KGM | B1S01W32 | NONE | NONE | NONE | NONE | 13391.75 | 2022-01-01 14:22:25.773 | 2022-01-01 14:43:09.060 |
732000049 | B1S01C03 | RAW MILK | 0 | KGM | B1S01W32 | NONE | NONE | NONE | NONE | 31993.42 | 2022-01-02 17:12:43.550 | 2022-01-02 17:57:51.643 |
732000049 | B1S01C04 | RAW MILK | 0 | KGM | B1S01W32 | NONE | NONE | NONE | NONE | 57417.7 | 2022-01-02 15:48:17.530 | 2022-01-02 17:12:40.333 |
This is just a sample to understand the situation.
Question: how can I get "FinalTable", without using the cursor fetch method?
I have tried using max(Amount)
, min(Start date)
, max(End date)
and tried grouping over MsgLinkId,MyRowId
but it didn't work.
This is my stored procedure:
CREATE PROCEDURE dbo.********
@UnitID nvarchar(50),
@WOID nvarchar(50),
@JobId nvarchar(50)= '',
@StartDate datetime = '',
@EndDate datetime = ''
AS
BEGIN
IF @EndDate = ''
BEGIN
SET @EndDate = @StartDate
END
SET @unitID = REPLACE(@unitId, 'All', '')
SET @WOID = REPLACE(@WOID, 'All', '')
SET @JobID = REPLACE(@JobId, 'All', '')
-- SET @startdate = REPLACE(@startdate, 'All', '')
-- SET @enddate = REPLACE(@enddate, 'All', '')
SELECT
T1.Msg_LinkId AS MsgLinkId,
ROW_NUMBER () OVER (PARTITION BY T1.Msg_LinkId
ORDER BY T2.DT_Msg Asc) MyRowid,
T1.Unit_WO AS WO_ID,
T3.Name AS SourceUnitName,
T4.Name AS MaterialName,
T1.Data_DInt04 AS BatchId,
T5.description AS UnitofMeasure,
T6.Name AS Segment1,
T7.Name AS Segment2,
T8.Name AS Segment3,
T9.Name AS Segment4,
T10.Name AS Segment5,
SUM(T2.Data_Real01) OVER (PARTITION BY T2.Msg_LinkId) Amount,
T1.DT_Msg AS StartDate,
T2.DT_Msg AS EndDate
INTO
#AuxTable
FROM
QHandler_Messages T1
LEFT JOIN
QHandler_Messages T2 ON T1.Unit_WO = T2.Unit_WO
AND T1.Msg_LinkId = T2.Msg_LinkId
LEFT JOIN
LK_CUSTOMDB.dbo.ListUnit T3 ON T1.Data_DInt02 = T3.ID
LEFT JOIN
LK_CUSTOMDB.dbo.vi_Materials T4 ON T1.Data_DInt03 = T4.Material_ID
LEFT JOIN
LK_CUSTOMDB.dbo.vw_uoms_all T5 ON T1.Data_DInt05 = T5.uom_id
LEFT JOIN
LK_CUSTOMDB.dbo.ListUnit T6 ON T1.Data_DInt06 = T6.ID
LEFT JOIN
LK_CUSTOMDB.dbo.ListUnit T7 ON T1.Data_DInt07 = T7.ID
LEFT JOIN
LK_CUSTOMDB.dbo.ListUnit T8 ON T1.Data_DInt08 = T8.ID
LEFT JOIN
LK_CUSTOMDB.dbo.ListUnit T9 ON T1.Data_DInt09 = T9.ID
LEFT JOIN
LK_CUSTOMDB.dbo.ListUnit T10 ON T1.Data_DInt10 = T10.ID
WHERE
(T1.unit_wo IN (SELECT CAST(splitdata AS nvarchar(max))
FROM dbo.ft_Admin_SplitString(@WOID, ','))
OR @WOID = '')
AND (T1.unit_id IN (SELECT CAST(splitdata AS nvarchar(max))
FROM dbo.ft_Admin_SplitString(@UnitID, ','))
OR @unitid = '')
AND T1.Msg_Identifier = 11
AND T2.Msg_Identifier = 12
AND (T1.Data_DInt01 IN (SELECT CAST(splitdata AS nvarchar(max))
FROM dbo.ft_Admin_SplitString(@JobID, ','))
OR @jobid = '')
UNION ALL
SELECT
T1.Msg_LinkId as MsgLinkId,
ROW_NUMBER () OVER (PARTITION BY T1.Msg_LinkId
ORDER BY T1.DT_Msg Asc) MyRowid,
T1.Unit_WO AS WO_ID,
T3.Name AS SourceUnitName,
T4.Name AS MaterialName,
T1.Data_DInt04 AS BatchId,
T5.description AS UnitofMeasure,
T6.Name AS Segment1,
T7.Name AS Segment2,
T8.Name AS Segment3,
T9.Name AS Segment4,
T10.Name AS Segment5,
SUM(T1.Data_Real01) OVER (PARTITION BY T1.Msg_LinkId) Amount,
T1.DT_Msg AS StartDate,
T1.DT_Msg AS EndDate
FROM
QHandler_Messages T1
LEFT JOIN
LK_CUSTOMDB.dbo.ListUnit T3 ON T1.Data_DInt02 = T3.ID
LEFT JOIN
LK_CUSTOMDB.dbo.vi_Materials T4 ON T1.Data_DInt03 = T4.Material_ID
LEFT JOIN
LK_CUSTOMDB.dbo.vw_uoms_all T5 ON T1.Data_DInt05 = T5.uom_id
LEFT JOIN
LK_CUSTOMDB.dbo.ListUnit T6 ON T1.Data_DInt06 = T6.ID
LEFT JOIN
LK_CUSTOMDB.dbo.ListUnit T7 ON T1.Data_DInt07 = T7.ID
LEFT JOIN
LK_CUSTOMDB.dbo.ListUnit T8 ON T1.Data_DInt08 = T8.ID
LEFT JOIN
LK_CUSTOMDB.dbo.ListUnit T9 ON T1.Data_DInt09 = T9.ID
LEFT JOIN
LK_CUSTOMDB.dbo.ListUnit T10 ON T1.Data_DInt10 = T10.ID
WHERE
(T1.unit_wo IN (SELECT CAST(splitdata AS nvarchar(max))
FROM dbo.ft_Admin_SplitString(@WOID, ','))
OR @WOID = '')
AND (T1.unit_id IN (SELECT CAST(splitdata AS nvarchar(max))
FROM dbo.ft_Admin_SplitString(@UnitID, ','))
OR @unitid = '')
AND T1.Msg_Identifier = 13
AND (T1.Data_DInt01 IN (SELECT CAST(splitdata AS nvarchar(max))
FROM dbo.ft_Admin_SplitString(@JobID, ','))
OR @jobid = '')
AND T1.DT_msg BETWEEN @StartDate
AND DATEADD(HOUR, 48, @EndDate)
SELECT *
FROM #AuxTable --- Result of Aux Table
DECLARE @Finaltable TABLE
(
MsgLinkId int,
Unit_WO bigint,
SourceUnitName nvarchar (255),
MaterialName nvarchar (255),
BatchId bigint,
UnitofMeasure nvarchar (255),
Segment1 nvarchar (255),
Segment2 nvarchar (255),
Segment3 nvarchar (255),
Segment4 nvarchar (255),
Segment5 nvarchar (255),
Amount real,
StartDate Datetime,
EndDate Datetime
)
DECLARE @MsgLinkId int
DECLARE @MyRowId int DECLARE cursorAux cursor for
select
MsgLinkId,
MyRowid
from
#Auxtable
open cursorAux FETCH NEXT
FROM
cursorAux INTO @MsgLinkId,
@MyRowid WHILE @@FETCH_STATUS = 0 BEGIN If Exists (
select
*
from
@Finaltable
where
MsgLinkId = @MsgLinkId
) Begin
Update
@Finaltable
Set
EndDate = (
Select
EndDate
from
#Auxtable where MsgLinkId = @MsgLinkId and MyRowid = @MyRowid)
Where
MsgLinkId = @MsgLinkId end ELSE Begin Insert into @Finaltable (
MsgLinkId, Unit_WO, SourceUnitName,
MaterialName, BatchId, UnitofMeasure,
Segment1, Segment2, Segment3, Segment4,
Segment5, Amount, StartDate, EndDate
)
select
MsgLinkId,
WO_ID,
SourceUnitName,
MaterialName,
BatchId,
UnitofMeasure,
Segment1,
Segment2,
Segment3,
Segment4,
Segment5,
Amount,
StartDate,
EndDate
from
#Auxtable
where
MsgLinkId = @MsgLinkId
and MyRowid = @MyRowid end FETCH NEXT
FROM
cursorAux INTO @MsgLinkId,
@MyRowid END CLOSE cursorAux;
DEALLOCATE cursorAux;
select
Unit_WO,
SourceUnitName,
MaterialName,
BatchId,
UnitofMeasure,
Segment1,
Segment2,
Segment3,
Segment4,
Segment5,
Amount,
StartDate,
EndDate
from
@Finaltable END GO
CodePudding user response:
Based on what the cursor appears to be doing, the below cte query should get your results. It appears the cursor is inserting the first MsgLinkId record (MyRowID = 1) and then updating the EndDate for any subsequent record. This query takes the first MsgLinkId record and joins to the last MsgLinkId record in order to take the EndDate, but retains all the other data from the first record.
;with cte as (
SELECT MsgLinkId,
MyRowId,
row_number() over(partition by MsgLinkId order by MyRowId desc) as MyRowIdDesc,
WO_ID,
SourceUnitName,
MaterialName,
BatchId,
UnitofMeasure,
Segment1,
Segment2,
Segment3,
Segment4,
Segment5,
Amount,
StartDate,
EndDate
FROM #AuxTable --- Result of Aux Table
)
select
row_first.Unit_WO,
row_first.SourceUnitName,
row_first.MaterialName,
row_first.BatchId,
row_first.UnitofMeasure,
row_first.Segment1,
row_first.Segment2,
row_first.Segment3,
row_first.Segment4,
row_first.Segment5,
row_first.Amount,
row_first.StartDate,
row_last.EndDate --On subsequent rows, only the EndDate appears to be updated
from
cte row_first
inner join
cte row_last on row_first.MsgLinkId = row_last.MsgLinkId and row_last.MyRowIdDesc = 1
where
row_first.MyRowId = 1 --The @Finaltable is first filled with the initial record