Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 规范化、聚合和联接表问题_Sql_Sql Server - Fatal编程技术网

Sql 规范化、聚合和联接表问题

Sql 规范化、聚合和联接表问题,sql,sql-server,Sql,Sql Server,假设我有一个客户数据库,他们购买的材料“适用于”随机对象。例如,John购买了10美元的适用于汽车和房子的“Material X” Customers +----+-------+ | ID | Name | +----+-------+ | 1 | John | | 2 | Larry | +----+-------+ Orders +---------+------------+-------+----------+ | OrderID | CustomerID | Sales |

假设我有一个客户数据库,他们购买的材料“适用于”随机对象。例如,John购买了10美元的适用于汽车和房子的“Material 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        |
+---------+------------+-------+----------+
我的
材料
表原来是这样的

+----------+-------------------------+
| Material |      Applicability      |
+----------+-------------------------+
| x        | car, house, plane, bike |
| y        | car, bike               |
+----------+-------------------------+
+----------+---------------+
| Material | Applicability |
+----------+---------------+
| x        | car           |
| x        | house         |
| x        | plane         |
| x        | bike          |
| y        | car           |
| y        | 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               |
+----+------+--------------+----------+-------------------------+
逗号分隔的值(我知道它违反了许多规则)很方便,因为在解析适用性时,我可以简单地用逗号分隔字符串,然后我就有了一个适用性对象列表

现在决定规范化
材质
表,所以现在看起来是这样的

+----------+-------------------------+
| Material |      Applicability      |
+----------+-------------------------+
| x        | car, house, plane, bike |
| y        | car, bike               |
+----------+-------------------------+
+----------+---------------+
| 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          |
+----+------+-------------+----------+---------------+
现在看来约翰买了100美元的材料x,而实际上他只买了25美元。我需要向用户展示John购买的材料x,以及x的适用性

主要的问题是当我需要知道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' and (applicability = 'car' or applicability = 'bike')
GROUP BY ID, Name, Material, Applicability
如果任何材料同时适用于汽车和自行车,则总价值
sum(sales)
将加倍

如何处理这种重复?

可能最简单的方法(对原始查询的修改最少)是先求和,然后加入适用性:

; 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

希望这就是你想要的

请相应地标记您的数据库。你想要的结果和原来的一样吗?如果是这样,您希望使用类似于
group\u concat
的方法将行重新组合到单个列中…添加了sql server标记。是的,结果应该是一样的,唯一的区别是标准化的Materials表。Sql Server不支持
组\u concat
。不过有几个例子说明了如何做到这一点。这有帮助吗:嗨,谢谢你的回答。如果我执行
操作,则仍然返回重复的行,其中适用性='car'或适用性='house'
。如果有一种材质同时适用于这两种材质,它将返回两行。我认为mySql的group_concat的模拟会起作用,但我不确定。