分组加入(多对多)

时间:2013-02-14 09:05:26

标签: sql tsql

我有2个表,产品和组件

CREATE TABLE Product(
ProductId uniqueidentifier DEFAULT NEWID(),
ProductName nvarchar(25) NOT NULL,
CONSTRAINT PK_Product PRIMARY KEY (ProductId))


CREATE TABLE Component
(
    ComponentId uniqueidentifier DEFAULT NEWID(),
    ComponentName nvarchar(25) NOT NULL,
    CONSTRAINT PK_Component PRIMARY KEY (ComponentId)
)

我需要一个“多对多”的连接,所以我创建了第三个表

CREATE TABLE Product_Component(
idProduct_Component uniqueidentifier DEFAULT NEWID(),
idProduct uniqueidentifier, 
idComponent uniqueidentifier,

 CONSTRAINT PK_idProduct_Component PRIMARY KEY (idProduct_Component),

CONSTRAINT FK_idComponent FOREIGN KEY (idComponent)
REFERENCES Component (ComponentId),
CONSTRAINT FK_idProduct FOREIGN KEY (idProduct)
REFERENCES Product (ProductId))

我添加了一些数据,现在我可以从表中select。产品可以包含许多组件,并且组件包含在许多产品中。现在我有Product两行 - 蛋糕和面包。在Component我有3排 - 糖,盐和面粉。我在表Product_Component中添加了值,现在我有一些想法像Cake包含糖和面粉,面包包括盐和面粉。我使用像这样的查询

SELECT Product.ProductName, Component.ComponentName FROM Product_Component
JOIN Component 
ON Product_Component.idComponent = Component.ComponentId 
JOIN Product
ON Product_Component.idProduct = Product.ProductId
WHERE Product.ProductName = 'Bread'

我看到了所有面包的组件,但每一行都是

bread | salt
bread | flour

我希望看到类似这样的内容

bread | salt
      | flour
      | some other component

我试过

SELECT Product.ProductName, Component.ComponentName FROM Product_Component
JOIN Component 
ON Product_Component.idComponent = Component.ComponentId 
JOIN Product
ON Product_Component.idProduct = Product.ProductId
WHERE Product.ProductName = 'Bread'
GROUP BY Product.ProductName

但我有留言

Column 'Component.ComponentName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

请帮助您进行正确的查询。

1 个答案:

答案 0 :(得分:3)

我认为在客户端应用程序中执行此操作会更好,更容易。 SQL与格式无关。

但是,如果您想在SQL中以任何方式执行此操作,您可以使用FOR XML对每个分组产品的组件名称进行分组,如下所示:

SELECT 
  p.ProductName, 
  STUFF((
    SELECT ', ' + c2.ComponentName 
    FROM Component AS c2
    WHERE c2.idComponent = pc.idComponent 
    FOR XML PATH (''))
  ,1,2,'') AS ComponentsNames
FROM Product_Component AS pc
JOIN Component         AS c ON pc.idComponent = c.ComponentId 
JOIN Product           AS p ON pc.idProduct   = p.ProductId
WHERE p.ProductName = 'Bread'
GROUP BY p.ProductName;