【问题标题】:SQL displaying rows with duplicate values in 3 RowsSQL 在 3 行中显示具有重复值的行
【发布时间】:2013-10-10 02:45:49
【问题描述】:

您好,我有一张下表说明价格

CostID   ItemID  Level  EffectiveFrom EffectiveTo            
6274751  12345   1       12/02/2013   NULL
6274751  12345   1       13/02/2013   NULL
6274751  12345   2       12/02/2013   NULL
6254784  12345   1       12/02/2013   NULL
6254784  12345   1       13/02/2013   NULL
6244784  12345   9       12/02/2013   NULL

我希望能够编写一个查询,通过比较 3 列“CostID”、“ItemID”和“Level”来查找重复的行,并仅显示重复的行

预期输出第 1 部分

CostID   ItemID  Level  EffectiveFrom EffectiveTo            
6274751  12345   1       12/02/2013   NULL
6274751  12345   1       13/02/2013   NULL
6254784  12345   1       12/02/2013   NULL
6254784  12345   1       13/02/2013   NULL

一旦我得到上面的结果,我想从最后一个重复行更新 EffectiveTo 表

第 2 部分的预期输出

CostID   ItemID  Level  EffectiveFrom EffectiveTo            
6274751  12345   1       12/02/2013   13/02/2013
6274751  12345   1       13/02/2013   NULL
6254784  12345   1       12/02/2013   13/02/2013
6254784  12345   1       13/02/2013   NULL

我试过了:

{
SELECT *
FROM price
WHERE ItemID IN
    (     SELECT ItemID
          FROM price
          GROUP BY ItemId          HAVING COUNT(distinct level) > 1
    )
ORDER BY CostID } 

对于查询的第一部分,但无法获得我想要的结果,我们将不胜感激。

谢谢

【问题讨论】:

  • 你用的是什么sql?
  • SQL Server 2005,感谢您帮我格式化
  • 你想确定的太多了。请具体。请提供您的预期输出。

标签: sql sql-server-2005


【解决方案1】:

这会给你重复的行:

select distinct p.*
from price p
join price q
    on p.CostID = q.CostID
    and p.ItemID = q.ItemID
    and p.Level = q.Level
    and p.EffectiveFrom != q.EffectiveFrom

条件p.EffectiveFrom != q.EffectiveFrom 很重要,因为它会阻止所有行加入自身。通常,您只需比较一个 id 列的不等式,但您的表似乎没有。


使用合适的结束日期更新旧行:

update p set
p.EffectiveTo = dateadd(day, -1, q.EffectiveFrom)
from price p
join price q
    on p.CostID = q.CostID
    and p.ItemID = q.ItemID
    and p.Level = q.Level
    and p.EffectiveFrom < q.EffectiveFrom

此查询的唯一真正区别是将不等式更改为小于,因此仅选择更新那些较早的行。

请注意,我已从较晚的日期中减去 1 天,因此没有重叠。

【讨论】:

  • 使用这个查询,我得到的结果太多了,如果我的表上有 41,000 条记录,运行查询后我得到 100,000 条记录。我只想看到大约 1,000 条重复记录,因此我可以手动执行第 2 部分。就像在我的示例中一样,我有 6 条记录,在运行查询后,我希望看到 4 条重复记录。谢谢
  • 您是否有几行(超过 2 行)具有相同的关键数据?
  • 当我运行第二个查询时,它说表“价格”不明确
  • 它会看到你有很多带有沙子值的记录,所以我添加了distinct 关键字来解决这个问题:第一个查询现在应该可以了。至于更新,我也纠正了这一点,尽管它对于多个共享记录要复杂得多。它会工作(不是错误),但你可以有几行具有相同的日期
  • 抱歉,我在 update p set 上使用 price 而不是,所以我收到了那个错误,但是一旦我修复了一个新错误,即 EffectiveTo 无法更新,但是我可以手动复制日期和时间并粘贴它,它工作正常。
【解决方案2】:

这个有点长……但你可以做一些改进。

;WITH cte AS
(
    SELECT ROW_NUMBER() OVER (PARTITION BY CostID, ItemID, Level ORDER BY CostID, EffectiveFrom) AS RNUM,
        CostID,
        ItemID,
        Level,
        EffectiveFrom,
        EffectiveTo
    FROM @Price
),
cteDup AS 
(
    SELECT DISTINCT CostID, ItemID, Level FROM cte WHERE RNUM > 1
)
SELECT tt.* FROM @Price tt
INNER JOIN cteDup cc ON tt.CostID = cc.CostID AND tt.ItemID = cc.ItemID AND tt.Level = cc.Level

更新:这将进行直接更新,但不确定这是否是您想要的。

;WITH cte AS
(
    SELECT ROW_NUMBER() OVER (PARTITION BY CostID, ItemID, Level ORDER BY CostID, EffectiveFrom) AS RNUM,
        CostID,
        ItemID,
        Level,
        EffectiveFrom,
        EffectiveTo
    FROM @Price
)
UPDATE c1 SET 
     EffectiveTo = c2.EffectiveFrom
FROM cte c1
INNER JOIN cte c2 ON c1.CostID = c2.CostID  AND c1.ItemID = c2.ItemID AND c1.Level = c2.Level AND c1.RNUM + 1 = c2.RNUM

【讨论】:

  • 这给了我完美的结果,但是一旦显示结果就无法更新。是否有无需执行第 1 部分即可实现第 2 部分的更新查询?
猜你喜欢
  • 2014-09-02
  • 2020-12-07
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 2018-02-09
  • 2012-01-20
  • 2017-01-03
  • 2019-07-06
相关资源
最近更新 更多