2

我有 2 张桌子

表名:Attributes

attribute_id  |   attribute_name

    1               attr_name_1
    2               attr_name_2
    3               attr_name_1
    4               attr_name_2

表名:Products

product_id    |   product_name    |    attribute_id
    1              prod_name_1              1
    2              prod_name_2              2
    3              prod_name_3              3
    4              prod_name_4              4

如果可以看到,attribute_idProducts中有以下 id 的(1,2,3,4),而不是(1,2,1,2).

问题出在表中Attributes,即存在attribute_names具有不同 ID 的重复值(),所以我想要:

  1. 从表中选择重复的一个 IDAttributes
  2. Products使用“挑选”的 ID更新表(仅在attribute_id表中具有相同名称的情况下Attributes
  3. 之后,从表中删除重复值,在表Attributes中没有用处Products

输出:

表名:Attributes

attribute_id  |   attribute_name
     1              attr_name_1
     2              attr_name_2

表名:Products

product_id    |   product_name    |    attribute_id
     1             prod_name_1              1
     2             prod_name_2              2
     3             prod_name_3              1
     4             prod_name_4              2

SQLFiddle上的演示

笔记:

如果我使用 sql 而不是手动修复此问题,它将对我有很大帮助。

4

2 回答 2

4
update Products
set attribute_id = (
    select min(attribute_id)
    from Attributes a
    where a.attribute_name=(select attribute_name from Attributes a2 where a2.attribute_id=Products.attribute_id)
);


DELETE
FROM Attributes
WHERE attribute_id NOT IN
(
    SELECT MIN(attribute_id)
    FROM Attributes
    GROUP BY attribute_name
);
于 2013-06-13T11:23:33.857 回答
1

以下可能比@Alexander Sigachov 的建议更快,但它确实需要至少 SQL Server 2005 才能运行它,而 Alexander 的解决方案可以在任何(合理的)SQL Server 版本上运行。尽管如此,即使只是为了提供替代方案,您也可以:

WITH Min_IDs AS (
  SELECT
    attribute_id,
    min_attribute_id = MIN(attribute_id) OVER (PARTITION BY attribute_name)
  FROM Attributes
)
UPDATE p
SET    p.attribute_id = a.min_attribute_id
FROM   Products p
JOIN   Min_IDs  a ON a.attribute_id = p.attribute_id
WHERE  a.attribute_id <> a.min_attribute_id
;

DELETE FROM Attributes
WHERE attribute_id NOT IN (
  SELECT attribute_id
  FROM   Products
  WHERE  attribute_id IS NOT NULL
)
;

第一个语句的CTE返回一个行集,其中每个attribute_id都映射到attribute_id相同的最小值attribute_name。通过加入这个映射集,UPDATE语句使用它来替换表attribute_id中的 s Products

随后从 中删除时Attributes,只需检查列中是否Attributes.attribute_id未找到就足够了Products.attribute_id,这就是第二条语句的作用。也就是说,此时不需要分组和聚合,就像另一个答案一样。

条件被添加到第二WHERE attribute_id IS NOT NULL个查询的子查询中,以防列可以为空并且可能确实包含 NULL。在这种情况下,NULL 需要被过滤掉,否则它们的存在会导致NOT IN谓词对 的求值UNKNOWN,SQL Server 会将其视为相同FALSE(因此不会有效地删除任何行)。如果 中不能有 NULL Products.attribute_id,则条件可能会被丢弃。

于 2013-06-19T06:36:34.580 回答