假设我有一个客户数据库,他们购买的材料是适用的"随机对象。例如,约翰买了10美元的材料X"适用于汽车和房屋。
Customers
+----+-------+
| ID | Name |
+----+-------+
| 1 | John |
| 2 | Larry |
+----+-------+
Orders
+---------+------------+-------+----------+
| OrderID | CustomerID | Sales | Material |
+---------+------------+-------+----------+
| 1 | 1 | 10 | x |
| 2 | 1 | 15 | x |
| 3 | 1 | 6 | y |
| 4 | 2 | 3 | x |
| 5 | 2 | 25 | y |
+---------+------------+-------+----------+
我的Materials
表最初看起来像这样
+----------+-------------------------+
| Material | Applicability |
+----------+-------------------------+
| x | car, house, plane, bike |
| y | car, bike |
+----------+-------------------------+
当我需要显示John购买的材料以及材料适用的对象时,我的查询是这样的。
Select ID, Name, sum(Sales), Material, Applicability
FROM Customers a
INNER JOIN Orders b on a.ID = b.CustomerID
INNER JOIN Materials c on b.Material = c.Material
WHERE Name = 'John'
GROUP BY ID, Name, Material, Applicability
结果
+----+------+--------------+----------+-------------------------+
| ID | Name | Total Sales | Material | Applicability |
+----+------+--------------+----------+-------------------------+
| 1 | John | 25 | x | car, house, plane, bike |
| 1 | John | 6 | y | car, bike |
+----+------+--------------+----------+-------------------------+
逗号分隔值(我知道它违反了许多规则)很方便,因为在解析适用性时,我可以简单地用逗号分割字符串,然后我有一个适用性对象列表。
现在已经决定对Materials
表进行规范化,所以现在它看起来像这样
+----------+---------------+
| Material | Applicability |
+----------+---------------+
| x | car |
| x | house |
| x | plane |
| x | bike |
| y | car |
| y | bike |
+----------+---------------+
此规范化已中断我现有的查询,导致sum(sales)
结果为材料适用的多个对象的倍数。
实施例
+----+------+-------------+----------+---------------+
| ID | Name | Total Sales | Material | Applicability |
+----+------+-------------+----------+---------------+
| 1 | John | 25 | x | car |
| 1 | John | 25 | x | house |
| 1 | John | 25 | x | plane |
| 1 | John | 25 | x | bike |
| 1 | John | 6 | y | car |
| 1 | John | 6 | y | bike |
+----+------+-------------+----------+---------------+
现在看来John已经购买了100美元的材料x,当时他真的只买了25美元。我需要向用户显示约翰购买材料x以及x的适用性。
主要问题是当我需要找出约翰购买的东西时,还要按适用性进行过滤。
Select ID, Name, sum(Sales), Material, Applicability
FROM Customers a
INNER JOIN Orders b on a.ID = b.CustomerID
INNER JOIN Materials c on b.Material = c.Material
WHERE Name = 'John' and (applicability = 'car' or applicability = 'bike')
GROUP BY ID, Name, Material, Applicability
如果任何材料适用于汽车和自行车,那么总价值sum(sales)
将加倍。
我如何处理这种重复?
答案 0 :(得分:0)
最简单的方法(对原始查询的修改最少)可以先加总,然后加入适用性:
; with CTE as (
Select ID, Name, sum(Sales) as TotalSales, material
From Customers a
inner join orders b
on a.ID = b.CustomerID
group by ID, Name, Material
)
select b.*, c.Applicability from CTE b
inner join Materials c on b.Material = c.Material
where...--insert selection criteria here
答案 1 :(得分:0)
SELECT 'x' as Material , 'car' as Applicability
INTO #Materials
UNION ALL
SELECT 'x' , 'house'
UNION ALL
SELECT 'x' , 'plane'
UNION ALL
SELECT 'x' , 'bike'
UNION ALL
SELECT'y' , 'car'
UNION ALL
SELECT 'y' , 'bike'
SELECT 1 as OrderID , 1 as CustomerID, 10 as Sales, 'x' as Material
INTO #Orders
UNION ALL
SELECT 2 , 1 , 15 , 'x'
UNION ALL
SELECT 3 , 1 , 6 , 'y'
UNION ALL
SELECT 4 , 2 , 3 , 'x'
UNION ALL
SELECT 5 , 2 , 25 , 'y'
SELECT 1 as ID , 'John' as Name
INTO #Customers
UNION ALL
SELECT 2 , 'Larry';
with CTE as (
SELECT ID, Name, sum(Sales) as TotalSales, c.material, Applicability
From #Customers a
inner join #orders b
on a.ID = b.CustomerID
inner join #Materials as c on c.Material = b.Material
where Name = 'John' and (applicability = 'car' or applicability = 'house')
group by ID, Name, c.Material, Applicability
)
SELECT ID, Name, TotalSales, Material, STUFF(
(SELECT distinct ',' + Applicability
FROM cte as c
where c.Material = c1.Material
FOR XML PATH (''))
, 1, 1, '') as Applicability
from CTE c1
group by ID, Name, TotalSales, Material
drop table #Customers
drop table #Orders
drop table #Materials
希望这就是你要找的东西。