4

我有以下 SQL Server 2008 表:

CREATE TABLE tbl (ID INT, dtIn DATETIME2, dtOut DATETIME2, Type INT, nID INT)
INSERT tbl VALUES
(1, '05:00', '10:00', 1, 1),  --will be changed
(2, '08:00', '16:00', 2, 1),
(3, '02:00', '08:00', 1, 1),  --will be changed
(4, '07:30', '11:00', 1, 1)

我使用以下 SQL 更新部分重叠的记录:

UPDATE tbl
SET dtOut = COALESCE((
    SELECT MIN(dtIn)
    FROM tbl as t2
    WHERE t2.type = tbl.type AND
          t2.id <> tbl.id AND
          t2.dtIn >= tbl.dtIn AND t2.dtIn < tbl.dtOut
    ), dtOut)
WHERE nID=1;

SELECT ROWCOUNT_BIG();

使用最后一个 SELECT 我想检索更新的记录数,但它不起作用。

所以我的问题是,我怎样才能重写这个语句来获得实际更新的记录数?(以上数据表中的2。)

4

3 回答 3

2

SQL Server 将更新原始示例中的所有行。像这样的东西怎么样:

WITH CTE AS (
    SELECT t1.ID, MIN(t2.dtIn) as New_dtOut
    FROM tbl as t1
    LEFT JOIN tbl AS t2 ON t2.type = t1.type AND t2.id <> t1.id
           AND t2.dtIn >= t1.dtIn AND t2.dtIn < t1.dtOut 
    WHERE t1.nID = 1
    GROUP BY t1.ID
)
UPDATE t1 SET dtOut = t2.New_dtOut
FROM tbl t1
JOIN CTE t2 on t2.ID = t1.ID 
WHERE t1.dtOut <> t2.New_dtOut

SELECT ROWCOUNT_BIG();
于 2012-07-22T06:39:43.973 回答
2

1.只需删除最后一个分号之前SELECT

UPDATE tbl
SET dtOut = COALESCE((
    SELECT MIN(dtIn)
    FROM tbl as t2
    WHERE t2.type = tbl.type AND
          t2.id <> tbl.id AND
          t2.dtIn >= tbl.dtIn AND t2.dtIn < tbl.dtOut
    ), dtOut)
WHERE nID=1
SELECT @@ROWCOUNT;

...它现在返回一些东西 - 4 - 这是因为 UPDATE 正在对所有行进行操作,而不仅仅是您需要的 2。

2. 越来越近 - 以下仅对类型 1 的 3 行进行操作:

update x  
set x.dtout = y.mn
from tbl x 
inner join  
  (  
  SELECT t1.type, min(t1.dtIn) mn
  FROM tbl t1
    inner join tbl t2
    on 
      t1.type = t2.type AND
      t1.id <> t2.id AND
      t1.dtIn >= t2.dtIn AND 
      t1.dtIn < t2.dtOut
  group by t1.type
  ) y
  on 
      x.type = y.type
SELECT @@ROWCOUNT; 

这是上面的 SQL 小提琴

3.感谢@Gilm,我已经完成了我希望没问题的事情;它与 Gilm 的 CTE 答案中使用的逻辑非常相似:

update x  
set x.dtout = y.mn
from tbl x 
inner join  
  (  
  SELECT t1.id, min(t2.dtIn) mn
  FROM tbl t1
    inner join tbl t2
    on 
      t1.type = t2.type AND
      t1.id <> t2.id AND
      t2.dtIn >= t1.dtIn AND 
      t2.dtIn < t1.dtOut
  group by t1.id
  ) y
  on 
      x.id = y.id
SELECT @@ROWCOUNT; 
SELECT * FROM tbl;

关于这里的 SQL 小提琴

于 2012-07-22T18:38:16.403 回答
2

WHERE nID=1正在决定将更新多少行。甚至您分配dtOut给自​​身的行也会被更新和计数。

您可以使用输出子句并在表变量中捕获更新的行,然后计算dtOut已更改的行。

DECLARE @T TABLE
(
  dtOutOld DATETIME2,
  dtOutNew DATETIME2
)

UPDATE tbl
SET dtOut = COALESCE((
    SELECT MIN(dtIn)
    FROM tbl as t2
    WHERE t2.type = tbl.type AND
          t2.id <> tbl.id AND
          t2.dtIn >= tbl.dtIn AND t2.dtIn < tbl.dtOut
    ), dtOut)
OUTPUT deleted.dtOut, inserted.dtOut INTO @T
WHERE nID=1

SELECT COUNT(*)
FROM @T 
WHERE dtOutOld <> dtOutNew

SQL小提琴

于 2012-07-23T07:32:35.197 回答