我有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_id
中的Products
具有以下ID (1,2,3,4)
,而不是(1,2,1,2)
。
问题出在表Attributes
中,即有不同ID的重复值(attribute_names
),所以我想:
Attributes
Products
(仅限attribute_id
表Attributes
中具有相同名称的情况)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而不是手动修复此问题,它会对我有很大的帮助。
答案 0 :(得分: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
);
答案 1 :(得分:1)
以下内容可能比@Alexander Sigachov's suggestion更快,但它至少需要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
语句使用它来替换{{1}}表中的attribute_id
。
当后来从Products
删除时,仅检查Attributes
列中是否找不到Attributes.attribute_id
就足够了,这就是第二个语句的作用。也就是说,此时不需要分组和聚合,如另一个答案所示。
Products.attribute_id
条件被添加到第二个查询的子查询中,以防该列可以为空并且可能确实包含NULL。在这种情况下需要过滤掉NULL,否则它们的存在会导致WHERE attribute_id IS NOT NULL
谓词对NOT IN
的评估,SQL Server会将其视为UNKNOWN
(因此 no 行将被有效删除)。如果FALSE
中不能有NULL,则可能会丢弃该条件。