用于连接并在多列中给出结果的 SQL 语句

Posted

技术标签:

【中文标题】用于连接并在多列中给出结果的 SQL 语句【英文标题】:SQL statement to join and give result in multiple columns 【发布时间】:2012-10-31 14:17:42 【问题描述】:

谁能帮我用一个 sql 语句来产生以下结果?

Table Person
Person_ID  Name
1          John
2          Paul

Table Declaration
Decl_ID             Person_ID   Amount
1                   1               10
2                   2               12
3                   1               99
4                   1               24

SQL 语句的结果应如下所示:

Name    Amount1 Amount2 Amount3
John    10      99      24
Paul    12

【问题讨论】:

@user1788822 所以如果Declaration 中有 1000000000000000000 条记录用于John,你会想要 1000000000000000000 列? 看起来像一个数据透视表,标准 sql 不适合。当您显示数据时,这种转换最好在客户端完成。 【参考方案1】:

您没有指定 RDBMS,但如果您的数据库有权访问该功能,这基本上是 pivot。如果没有,那么您可以使用 case 和聚合函数进行复制。

MySQL

select name,
  sum(case when group_rn = 1 then amount else 0 end) Amount1,
  sum(case when group_rn = 2 then amount else 0 end) Amount2,
  sum(case when group_rn = 3 then amount else 0 end) Amount3
from
(
  select name,
    @num := if(@name = `name`, @num + 1, 1) as group_rn,
    @name := `name` as dummy,
    amount
  from
  (
    select p.name,
      d.amount,
      d.decl_id
    from person p
    inner join declaration d
      on p.person_id = d.person_id
  ) src
  order by name
) p
group by name

见SQL Fiddle with Demo

在 SQL Server 和 Oracle 中存在 PIVOT 函数:

SQL Server

select name,
  [1] as Amount1,
  [2] as Amount2,
  [3] as Amount3
from
(
  select p.name,
    d.amount,
    row_number() over(partition by p.name order by d.amount) rn
  from person p
  inner join declaration d
    on p.person_id = d.person_id
) src
pivot
(
  sum(amount)
  for rn in ([1], [2], [3])
) p

见SQL Fiddle with Demo

您可以创建动态版本,以防您想要转换成列的金额数量未知。

编辑,您说您使用的是 Oracle,所以 oracle 具体答案如下:

Oracle 11g 有pivot 函数:

select name,
  Amount1,
  Amount2,
  Amount3
from
(
  select p.name,
    d.amount,
    row_number() over(partition by p.name order by d.amount) rn
  from person p
  inner join declaration d
    on p.person_id = d.person_id
) src
pivot
(
  sum(amount)
  for rn in ('1' as Amount1, '2' as Amount2, '3' as Amount3)
) p

见SQL Fiddle with Demo

如果您不在 Oracle 11g 上,则需要使用 CASE 和聚合函数:

select name,
  sum(case when rn = 1 then amount else 0 end) Amount1,
  sum(case when rn = 2 then amount else 0 end) Amount2,
  sum(case when rn = 3 then amount else 0 end) Amount3
from
(
  select p.name,
    d.amount,
    row_number() over(partition by p.name order by d.amount) rn
  from person p
  inner join declaration d
    on p.person_id = d.person_id
) src
group by name

见SQL Fiddle with Demo

【讨论】:

谢谢!!不知道有这样的枢轴功能。 @user1788822 是的,oraclesql server 都有 pivot 功能。对于这些类型的结果,它会派上用场。 PIVOT 函数仅在 11g 中可用,所以在此之前,您将需要使用带有聚合函数的 case @user1788822 您是否需要将未知数量的金额值转换为列? 不,最多 10 个数量,感谢所有答案! @user1788822 如果任何答案有帮助,请务必通过左侧的复选标记接受。它将帮助未来的访问者和您从接受中获得声誉。 :)【参考方案2】:

我认为您正在寻找的是动态支点。 问题是当您需要动态数据透视时,您需要将查询作为字符串执行。

查找示例:http://www.sqlhub.com/2009/05/generic-stored-procedure-for-pivot-in.html

【讨论】:

以上是关于用于连接并在多列中给出结果的 SQL 语句的主要内容,如果未能解决你的问题,请参考以下文章

sql中一对多关系的查询结果的多行转换成一行多列

JDBC结果集

MySQL_select distinct无法实现只对单列去重,并显示多列结果的解决方法

Sql 从一个表列中选择一个最小值,并在一个 SQL 语句中将结果插入到另一个表列中

SQL逗号分割一列数据的值,将结果变成一行多列

mysql 将两个SQL语句查询结果并在一起