[英]Recursive Matching using CTE Query in SQL Server
我有兩個表(它們在下面定義,您可以使用下面的SQL來構建它們)
IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'ETab')
DROP TABLE ETab;
GO
CREATE TABLE ETab
([MRN] varchar(20), [LSPEC] varchar(2), [ADT] DATETIME, [SDT] DATETIME, [Source] varchar(20), [Enum] varchar(20));
GO
INSERT INTO ETab ([MRN], [LSPEC], [ADT], [SDT], [Source], [Enum])
VALUES
('HOMECARE', 'HM', CONVERT(datetime, '2017-04-01 00:00:00.000', 20), CONVERT(datetime, '2017-04-30 00:00:00.000', 20), 'PRODPAT', 'HOMEBLD04'),
('HOMECARE', 'HM', CONVERT(datetime, '2017-05-01 00:00:00.000', 20), CONVERT(datetime, '2017-05-31 00:00:00.000', 20), 'PRODPAT', 'HOMEBLD05'),
('HOMECARE', 'HM', CONVERT(datetime, '2017-06-01 00:00:00.000', 20), CONVERT(datetime, '2017-06-30 00:00:00.000', 20), 'PRODPAT', 'HOMEBLD06'),
('HOMECARE', 'HM', CONVERT(datetime, '2017-07-01 00:00:00.000', 20), CONVERT(datetime, '2017-07-31 00:00:00.000', 20), 'PRODPAT', 'HOMEBLD07'),
('HOMECARE', 'HM', CONVERT(datetime, '2017-08-01 00:00:00.000', 20), CONVERT(datetime, '2017-08-31 00:00:00.000', 20), 'PRODPAT', 'HOMEBLD08'),
('HOMECARE', 'HM', CONVERT(datetime, '2017-09-01 00:00:00.000', 20), CONVERT(datetime, '2017-09-30 00:00:00.000', 20), 'PRODPAT', 'HOMEBLD09'),
('HOMECARE', 'HQ', CONVERT(datetime, '2017-04-01 00:00:00.000', 20), CONVERT(datetime, '2017-04-30 00:00:00.000', 20), 'PRODPAT', 'HOMEDRG04HM'),
('HOMECARE', 'HM', CONVERT(datetime, '2017-05-01 00:00:00.000', 20), CONVERT(datetime, '2017-05-31 00:00:00.000', 20), 'PRODPAT', 'HOMEDRG05HM'),
('HOMECARE', 'HM', CONVERT(datetime, '2017-06-01 00:00:00.000', 20), CONVERT(datetime, '2017-06-30 00:00:00.000', 20), 'PRODPAT', 'HOMEDRG06HM'),
('HOMECARE', 'HM', CONVERT(datetime, '2017-07-01 00:00:00.000', 20), CONVERT(datetime, '2017-07-31 00:00:00.000', 20), 'PRODPAT', 'HOMEDRG07HM'),
('HOMECARE', 'HM', CONVERT(datetime, '2017-08-01 00:00:00.000', 20), CONVERT(datetime, '2017-08-31 00:00:00.000', 20), 'PRODPAT', 'HOMEDRG08HM'),
('HOMECARE', 'HM', CONVERT(datetime, '2017-09-01 00:00:00.000', 20), CONVERT(datetime, '2017-09-30 00:00:00.000', 20), 'PRODPAT', 'HOMEDRG09HM'),
('111824', 'UR', CONVERT(datetime, '2017-09-22 00:00:00.000', 20), CONVERT(datetime, '2017-09-22 00:00:00.000', 20), 'OP', 'OP1118240003'),
('111824', 'NL', CONVERT(datetime, '2017-04-19 00:00:00.000', 20), CONVERT(datetime, '2017-04-19 00:00:00.000', 20), 'OP', 'OP1118240001'),
('111824', 'MS', CONVERT(datetime, '2017-06-30 00:00:00.000', 20), CONVERT(datetime, '2017-06-30 00:00:00.000', 20), 'OP', 'OP1118240002'),
('111824', 'MS', CONVERT(datetime, '2017-04-24 00:00:00.000', 20), CONVERT(datetime, '2017-04-24 00:00:00.000', 20), 'IP', 'IP1118240001'),
('111824', 'MS', CONVERT(datetime, '2017-04-28 00:00:00.000', 20), CONVERT(datetime, '2017-04-28 00:00:00.000', 20), 'IP', 'IP1118240005'),
('111824', 'MS', CONVERT(datetime, '2017-04-27 00:00:00.000', 20), CONVERT(datetime, '2017-04-27 00:00:00.000', 20), 'IP', 'IP1118240004'),
('111824', 'MS', CONVERT(datetime, '2017-04-26 00:00:00.000', 20), CONVERT(datetime, '2017-04-26 00:00:00.000', 20), 'IP', 'IP1118240003'),
('111824', 'MS', CONVERT(datetime, '2017-04-25 00:00:00.000', 20), CONVERT(datetime, '2017-04-25 00:00:00.000', 20), 'IP', 'IP1118240002');
GO
IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'UTab')
DROP TABLE UTab;
GO
CREATE TABLE UTab
(MRN varchar(20), SIDate DATETIME, LSPEC varchar(2), Source varchar(20), Enum varchar(20), Iteration varchar(20));
GO
INSERT INTO UTab
(MRN, SIDate, LSPEC, Source, Enum, Iteration)
VALUES
('HOMECARE', CONVERT(datetime, '2017-04-20 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-20 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-20 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-20 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-20 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-20 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-30 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-30 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-30 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-20 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-30 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-30 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-17 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-30 00:00:00.000', 20), 'HQ', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-30 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-04-30 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-30 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-01 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-01 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-01 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-01 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-01 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-01 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-30 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-01 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-06-26 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-30 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-30 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('HOMECARE', CONVERT(datetime, '2017-05-04 00:00:00.000', 20), 'HM', 'N', NULL, NULL),
('111824', CONVERT(datetime, '2017-04-21 00:00:00.000', 20), 'MS', 'IP', NULL, NULL),
('111824', CONVERT(datetime, '2017-04-24 00:00:00.000', 20), 'NL', 'OP', NULL, NULL),
('111824', CONVERT(datetime, '2017-04-27 00:00:00.000', 20), 'NL', 'OP', NULL, NULL),
('111824', CONVERT(datetime, '2017-04-20 00:00:00.000', 20), 'NL', 'OP', NULL, NULL),
('111824', CONVERT(datetime, '2017-04-20 00:00:00.000', 20), 'NL', 'OP', NULL, NULL),
('111824', CONVERT(datetime, '2017-04-20 00:00:00.000', 20), 'NL', 'OP', NULL, NULL);
GO
SELECT * FROM ETab
WHERE Source = 'PRODPAT' AND LSPEC = 'HM'
GO
SELECT * FROM UTab
WHERE LSPEC = 'HM';
GO
IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '__Tmp')
DROP TABLE __Tmp;
GO
我有一個C#應用程序,用戶在運行時請求certian匹配子句。 使用用戶指定的信息,我生成一些執行的SQL並更新UTab
。
通過生成的SQL,我希望執行一些匹配,根據鏈接字段[MRN]
更新[UTab].[Enum]
[MRN]
以及[UTab].[SIDate]
位於[ETab].[ADT]
和[ETab].[SDT]
[ETab].[ADT]
[ETab].[SDT]
+ - 用戶指定的前幾天或之后的某天。 因此,用戶可以指定兩個命令,第一個:
MatchCmd:MRN,LSPEC:ETab:UTab:ADT:SDT:SIDate:0:1:'Iteration#1':WHERE [UTab].[Source] = 'OP' AND [UTab].[LSPEC] = [ETab].[LSPEC]
這說,從源表
ETab
匹配MRN
和LSPEC
,更新UTab
,其中SIDate > ADT - 0 day(s)
和SIDate < SDT + 1 day(s)
和[UTab].[Source] = 'OP'
- 任何匹配我用“迭代次數”Iteration#1
標記。
我的代碼生成以下SQL:
;WITH cte AS (
SELECT [ETab].[Enum] AS Enum,
[ETab].[MRN] AS Link,
[ETab].[ADT] AS ADT,
[ETab].[SDT] AS SDT,
[UTab].[SIDate] AS DT,
[ETab].[MRN] AS [MRN],
[ETab].[LSPEC] AS [LSPEC],
[ETab].[Source] AS [Source],
ROW_NUMBER() OVER (PARTITION BY [UTab].[MRN], [UTab].[LSPEC], [UTab].[SIDate]
ORDER BY ABS(DATEDIFF(mi, [UTab].[SIDate], [ETab].[ADT]))) AS Idx,
ABS(DATEDIFF(mi, [UTab].[SIDate], [ETab].[ADT])) AS Diff
FROM [UTab]
LEFT JOIN [ETab] ON [UTab].[MRN] = [ETab].[MRN]
WHERE ([UTab].[SIDate] BETWEEN
DATEADD(dd, -0, [ETab].[ADT]) AND
DATEADD(dd, 1, [ETab].[SDT]) AND [Iteration] IS NULL)
AND ETab.Source = 'OP'
) SELECT *
INTO __Tmp
FROM cte;
GO
獲取符合條件的所有記錄(在時間窗口內放置並遵守自定義where子句)。 然后我通過另一個生成的查詢更新[UTab].[Enum]
和[UTab].[Iteration]
UPDATE [UTab]
SET [ENum] = [__Tmp].[ENum], [Iteration] = N'Iteration#1'
--SELECT __Tmp.ENum, __Tmp.Link, __Tmp.LSPEC, __Tmp.ADT, __Tmp.SDT, __Tmp.DT, __Tmp.Idx
FROM [UTab] AS up
INNER JOIN [__Tmp]
ON [up].[MRN] = [__Tmp].[Link]
AND [up].[SIDate] = [__Tmp].[DT]
AND [up].[LSPEC] = [__Tmp].[LSPEC]
WHERE __Tmp.Idx = 1;
這似乎工作正常,但有些問題:
問:我使用的方法/ SQL有什么明顯的問題嗎?
謝謝你的時間。
up.L != cte.L
因為您正在尋找符合您條件並按rn
過濾的任何內容。
SELECT cte.E, [Iteration] = N'00-00-00-CA', *
FROM [Up]
INNER JOIN cte ON [Up].[M] = [cte].[M] AND [cte].[rn] = 1
WHERE [cte].[E] IS NOT NULL AND (
[Up].[DTE] BETWEEN
DATEADD(dd, -0, [cte].[ADT]) AND
DATEADD(dd, 0, [cte].[SDT]))
AND [Up].[F] = 'Y'
AND [Up].[S] = 'HC'
----comment this line
--AND [Up].[L] = [cte].[L]; -- <<<<<<<<<<<<<<<<
http://sqlfiddle.com/#!18/d1483/2/0
我修改了一些數據:添加ZZ
完全破壞了你的查詢。 只有兩行匹配。
ps固定插入問題,第一個插入中列出了E
列和列名稱的長度。
CTE的用法對我來說有點奇怪,因為在后續查詢中你並沒有真正做很多事情。 我會把它移到更新。
該查詢並未真正加入Source 。 我不確定這是否意味着這樣做。 如果UTab有多個MRN / LSPEC組合源,則可能會導致問題。
所以,我想出了類似的東西:
DECLARE @ADT_Adjustment INT = 0;
DECLARE @SDT_Adjustment INT = 1;
DECLARE @Iteration INT = 1;
WITH SequencedJoin AS (
SELECT
ETab.MRN, ETab.LSPEC, ETab.ADT, ETab.SDT, UTab.SIDate, ETab.Enum, ETab.[Source], UTab.Enum AS WriteEnum, UTab.Iteration AS WriteIteration
, DENSE_RANK() OVER (
PARTITION BY UTab.MRN, UTab.LSPEC, UTab.[Source], UTab.SIDate
ORDER BY ABS( DATEDIFF( MINUTE, UTab.SIDate, ETab.ADT ) )
) AS Ordinal
FROM
@UTab AS UTab
JOIN @ETab AS ETab ON (
ETab.MRN = UTab.MRN
AND ETab.LSPEC = UTab.LSPEC
AND ETab.[Source] = UTab.[Source]
AND UTab.SIDate BETWEEN DATEADD( dd, -@ADT_Adjustment, ETab.ADT ) AND DATEADD( dd, @SDT_Adjustment, ETab.SDT )
)
WHERE
UTab.Iteration IS NULL
)
UPDATE
SequencedJoin
SET
WriteEnum = SequencedJoin.Enum
, WriteIteration = N'Iteration#' + CAST( @Iteration AS VARCHAR( 2 ) )
WHERE
SequencedJoin.[Source] = 'OP'
AND SequencedJoin.Ordinal = 1
這不是一個完整的答案,但這個指數會加速你CTE:
CREATE INDEX T1 ON UTAB (
MRN,
SIDATE
)
INCLUDE
(
LSPEC,
Iteration
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.