计算“复杂”t-SQL语句中的更新记录

时间:2012-07-22 06:16:13

标签: sql sql-server tsql sql-update rowcount

我有以下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个。)

3 个答案:

答案 0 :(得分: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();

答案 1 :(得分: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; 

HERE IS THE SQL FIDDLE OF THE ABOVE

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;

ON SQL FIDDLE HERE

答案 2 :(得分:2)

WHERE nID=1决定将更新多少行。即使您为自己指定dtOut的行也会更新并计算在内。

您可以使用output子句捕获表变量中的更新行,然后计算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-Fiddle