我想根据 customer_code列和品牌列<更新“品牌A”,“品牌B”和“品牌C”列,其结果为“true”或“false” / b>。
例如,表市场显示以下内容: 我有一个顾客买了A和B品牌:
Customer_code Brand Brand A Brand B Brand C
1234567 A NULL NULL NULL
1234567 B NULL NULL NULL
Customer_code Brand Brand A Brand B Brand C
1234567 A True True False
1234567 B True True False
由于我有大量数据,所以有什么方法可以解决这个问题吗?
非常感谢你!
答案 0 :(得分:2)
以这种方式存储数据有很多或冗余:
Customer_code Brand Brand A Brand B Brand C
1234567 A True True False
1234567 B True True False
存储它的正常方法就是:
Customer_code Brand
1234567 A
1234567 B
由于您的真/假列基于前两个数据,因此存储它们是一个坏主意,因为您有另外的任务来保持其准确性。
想象一下,我向你的表中插入了一个新行,即使我为每个品牌插入了正确的true / false值,它仍会使前两行错误:
Customer_code Brand Brand A Brand B Brand C
1234567 A True True False
1234567 B True True False
1234567 C True True True
正如我所说,我建议只存储customer_code和品牌,其余的可以从这两列中计算出来。最后,我还建议使用BIT DataType来表示布尔值,而不是将true或false存储为文本(SQL Server中没有布尔类型)。所以你可以创建一个视图:
SELECT pvt.Customer_Code,
[Brand A] = CAST(CASE WHEN pvt.[A] > 0 THEN 1 ELSE 0 END AS BIT),
[Brand B] = CAST(CASE WHEN pvt.[B] > 0 THEN 1 ELSE 0 END AS BIT),
[Brand C] = CAST(CASE WHEN pvt.[C] > 0 THEN 1 ELSE 0 END AS BIT)
FROM ( SELECT Customer_Code, Brand, Value = 1
FROM T
) T
PIVOT
( COUNT(Value)
FOR Brand IN ([A], [B], [C])
) pvt;
这给出了以下结果:
Customer_code | Brand A | Brand B | Brand C
--------------+---------+---------+----------
1234567 | 1 | 1 | 0
<强> Example on SQL Fiddle 强>
它没有品牌专栏,但这是多余的,因为品牌是每个品牌的位栏所暗示的,因此包括品牌只会导致重复的行。
最后,要真正回答您的问题,您可以使用以下内容实际进行更新:
WITH PVT AS
( SELECT Customer_Code, [A], [B], [C]
FROM ( SELECT Customer_Code, Brand, Value = 1
FROM T
) T
PIVOT
( COUNT(Value)
FOR Brand IN ([A], [B], [C])
) pvt
)
MERGE T
USING PVT
ON PVT.Customer_Code = T.Customer_Code
WHEN MATCHED THEN UPDATE
SET [Brand A] = CASE WHEN pvt.A > 0 THEN 'True' ELSE 'False' END,
[Brand B] = CASE WHEN pvt.B > 0 THEN 'True' ELSE 'False' END,
[Brand C] = CASE WHEN pvt.C > 0 THEN 'True' ELSE 'False' END;
<强> Example on SQL Fiddle 强>
或SQL Servier特定的UPDATE / FROM语法:
WITH PVT AS
( SELECT Customer_Code, [A], [B], [C]
FROM ( SELECT Customer_Code, Brand, Value = 1
FROM T
) T
PIVOT
( COUNT(Value)
FOR Brand IN ([A], [B], [C])
) pvt
)
UPDATE T
SET [Brand A] = CASE WHEN pvt.A > 0 THEN 'True' ELSE 'False' END,
[Brand B] = CASE WHEN pvt.B > 0 THEN 'True' ELSE 'False' END,
[Brand C] = CASE WHEN pvt.C > 0 THEN 'True' ELSE 'False' END
FROM T
INNER JOIN PVT
ON PVT.Customer_Code = T.Customer_Code;
<强> Example on SQL Fiddle 强>
答案 1 :(得分:0)
使用子查询:
UPDATE m
SET Brand_A = CASE WHEN EXISTS(SELECT 1 FROM dbo.Market m2
WHERE m.Customer_code = m2.Customer_code
AND m2.Brand = 'A') THEN 1 ELSE 0 END,
Brand_B = CASE WHEN EXISTS(SELECT 1 FROM dbo.Market m2
WHERE m.Customer_code = m2.Customer_code
AND m2.Brand = 'B') THEN 1 ELSE 0 END,
Brand_C = CASE WHEN EXISTS(SELECT 1 FROM dbo.Market m2
WHERE m.Customer_code = m2.Customer_code
AND m2.Brand = 'C') THEN 1 ELSE 0 END
FROM dbo.Market m
答案 2 :(得分:0)
create table market
(customer_code varchar(200),
brand char(1),
brand_a int,
brand_b int,
brand_c int
);
insert into market values('1234567','A',0,0,0);
insert into market values('1234567','B',0,0,0);
UPDATE market
SET brand_a = a, brand_b = b, brand_c = c
FROM
(
SELECT customer_code c_code,
MAX(CASE WHEN brand = 'A' THEN 1 ELSE NULL END) over(PARTITION by customer_code) a,
MAX(CASE WHEN brand = 'B' THEN 1 ELSE NULL END) over(PARTITION by customer_code) b,
MAX(CASE WHEN brand = 'C' THEN 1 ELSE NULL END) over(PARTITION by customer_code) c
FROM market
) aa
WHERE customer_code = c_code;
另外一件事就是删除不需要的列,只将客户和品牌存储在数据库中,稍后再使用查询:
SELECT
customer_code,
MAX(CASE WHEN brand='A' THEN 1 ELSE 0 END) AS brand_a,
MAX(CASE WHEN brand='B' THEN 1 ELSE 0 END) AS brand_b,
MAX(CASE WHEN brand='C' THEN 1 ELSE 0 END) AS brand_c
FROM market
GROUP BY customer_code;