mysql - 如何转动?如何将多行转换为多列的一行?

标签 mysql sql sql-server pivot-table

我有两个要合并的表。第一张 table 是客户,另一张 table 是产品。目前我有 22 种产品,但我希望有一个灵活的数据库设计,所以我没有在产品数据库中有 22 列,而是为每个客户的每个产品分配 1 行,所以如果我总体上添加或删除 1 个产品,我不会必须更改数据库结构。

我想要一个选择语句,我在其中为每个客户选择所有产品,输出应该在一行中,每个产品有一列。

我看到了其他一些类似的问题,但目的是将所有行连接在 1 列中——我不希望这样。

假设有 2 个客户和 3 个产品。

表客户端:

ClientId | ClientName
---------------------
 1       | Name1
 2       | Name2

餐 table 用品

ProductId | ClientId | Product
-------------------------------------
 1        |   1      |  SomeproductA
 2        |   1      |  SomeproductB
 3        |   1      |  SomeproductA
 4        |   2      |  SomeproductC
 5        |   2      |  SomeproductD
 6        |   2      |  SomeproductA

输出应该是这样的:

表输出:

 ClientId | ClientName | Product1     | Product 2    | Product 3
 -------------------------------------------------------------------
     1    | Name1      | SomeproductA | SomeproductB | SomeproductA
     2    | Name2      | SomeproductC | SomeproductD | SomeproductA

完美的解决方案也应该是灵活的,因为选择语句应该计算每个客户的不同产品的数量(它们对所有客户总是相同的),这样如果我为所有客户添加或删除 1 个产品客户,我不应该更改选择语句。

最佳答案

MYSQL版

这是查询。连接查询使用 User Defined Variables MySQL feature 为每个客户组内的每个产品生成 RowNumber (1,2,3,...) .外部查询使用 GROUP BY 和 CASE 以及来自内部表的行号形成一个 PIVOT 表。如果您需要可变产品列数,请考虑创建此查询动态添加 MAX(CASE WHEN p.RowNum=X THEN p.Product END) as ProductX 到选择列表。

select Clients.ClientName,
       MAX(CASE WHEN p.RowNum=1 THEN p.Product END) as Product1,
       MAX(CASE WHEN p.RowNum=2 THEN p.Product END) as Product2,
       MAX(CASE WHEN p.RowNum=3 THEN p.Product END) as Product3,
       MAX(CASE WHEN p.RowNum=4 THEN p.Product END) as Product4


FROM Clients
JOIN
(
  SELECT Products.*,
       if(@ClientId<>ClientId,@rn:=0,@rn),
       @ClientId:=ClientId,
       @rn:=@rn+1 as RowNum

  FROM Products, (Select @rn:=0,@ClientId:=0) as t
  ORDER BY ClientId,ProductID
 ) as P 
   ON Clients.ClientId=p.ClientId

GROUP BY Clients.ClientId

SQLFiddle demo

SQL Server 版本:

select Clients.ClientId,
       MAX(Clients.ClientName),
       MAX(CASE WHEN p.RowNum=1 THEN p.Product END) as Product1,
       MAX(CASE WHEN p.RowNum=2 THEN p.Product END) as Product2,
       MAX(CASE WHEN p.RowNum=3 THEN p.Product END) as Product3,
       MAX(CASE WHEN p.RowNum=4 THEN p.Product END) as Product4


FROM Clients
JOIN
(
  SELECT Products.*,
       ROW_NUMBER() OVER (PARTITION BY ClientID ORDER BY ProductID) 
         as RowNum

  FROM Products
 ) as P 
   ON Clients.ClientId=p.ClientId
GROUP BY Clients.ClientId

SQLFiddle demo

关于mysql - 如何转动?如何将多行转换为多列的一行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20676984/

相关文章:

python - 我应该为 'social' 网站的后端使用什么?

mysql - 将用户地址存储到欧洲数据库的最佳方法?

mysql - mysql 中的 desc 表说 Null 为 No 但默认为 NULL?

mysql - 如何组合这两个表,以便我可以对每个表上的信息进行排序,但不会得到重复的答案?

sql-server - 非企业版SQL Server在线索引

php - mysql_query 问题 - 语法错误

mysql - 如何在 knex 中使用 'and' 和 'on' 连接条件

sql - 部分不同的选择

sql-server - 分层组的数据库架构

c# - 从图像列可能为空的数据库加载图片框图像