我试图忽略来自 CTE 的重复行,但我无法做到这一点,似乎 CTE 不允许使用ROWNUM()变量到WHERE子句,因为它在尝试这样做时显示“无效的列名 'numrows' ”错误.
SELECT在 a 中使用时如何忽略重复的行CTE?
SQL查询:
DECLARE @BatchID uniqueidentifier = NEWID();
DECLARE @ClusterID SMALLINT = 1;
DECLARE @BatchSize integer = 20000;
DECLARE @myTableVariable TABLE(
EventID BIGINT,
HotelID int,
BatchStatus varchar(50),
BatchID uniqueidentifier);
WITH PendingExtResSvcEventsData_Batch AS (
SELECT TOP (@BatchSize) t.EventID, t.HotelID, t.BatchStatus, t.BatchID,
ROW_NUMBER() OVER (PARTITION BY t.EventID ORDER BY t.EventID) numrows
FROM ExtResSvcPendingMsg t WITH (NOLOCK)
WHERE t.ClusterID = @ClusterID
AND numrows = 1
-- Exclude ExtResSvcEventID and HotelID,
-- which are partly included in in-progress batch.
AND NOT EXISTS (
select 1 from ExtResSvcPendingMsg t2
where t2.BatchStatus = 'Batched'
and t2.EventID = t.EventID and t2.HotelID = t.HotelID
)
)
UPDATE PendingExtResSvcEventsData_Batch
SET BatchStatus='Batched',
BatchID = @BatchID
OUTPUT INSERTED.* INTO @myTableVariable --WHERE numrows = 1
SELECT e.ExtResSvcEventID, e.HotelID, e.ID1, e.ID2, e.ExtResSvcEventType, e.HostID,
e.StatusCode, e.ChannelID, e.RequestAtTime, e.ProcessTime, e.DateBegin, e.DateEnd,
e.StatusMsg, em.MsgBodyOut, em.MsgBodyIn, e.ChannelResID
FROM ExtResSvcEvent e WITH (NOLOCK)
INNER JOIN @myTableVariable t ON e.ExtResSvcEventID = t.EventID
INNER JOIN ExtResSvcEventXML em WITH (NOLOCK) ON t.EventID = em.ExtResSvcEventID
ORDER BY e.ExtResSvcEventID
Run Code Online (Sandbox Code Playgroud)
不要INSERTED.*在这里使用:
OUTPUT INSERTED.* INTO @myTableVariable
Run Code Online (Sandbox Code Playgroud)
相反,明确列出列:
OUTPUT INSERTED.EventID,
INSERTED.HotelID,
INSERTED.BatchStatus,
INSERTED.BatchID
INTO @myTableVariable
Run Code Online (Sandbox Code Playgroud)
该*方法的所有目标数据集的列。您案例中的目标数据集是一个 CTE,除了普通列之外,它还返回一个计算列。该INSERTED.*语法包括计算列太多,但引用计算的列在这方面是不允许的。列出所有必需的列可以明确解决该问题。
您可以numrows在该 UPDATE 上使用过滤器(但不能在 CTE 内使用)。numrows除了 OUTPUT 子句和 SET 子句中赋值的左侧,该引用在任何地方都有效。
这是一个演示,它无耻地借用了 ypercube?? 的设置以及他的 UPDATE 语句。