基于同一表上的值,在同一行上返回多个值

时间:2011-11-01 19:53:53

标签: sql oracle pivot

我已经很难过了一段时间,一直试图根据其他结果从我们的一张表中得到结果,而且每个值都没有返回多行,所以我很难解释,所以我会给一个示例

我们有一个值,例如,APPLES。每个苹果都有自己的序列号SERIAL。对于某些APPLES,有多个(最多6个)SERIAL值。

ID      APPLE       SERIAL
2052    5035        1
2055    5035        4
2058    5035        8
2070    5040        5

在我的结果中,我想要返回每个APPLE一次,并将所有序列分配给它,例如:

APPLE   SERIAL_1    SERIAL_2    SERIAL_3    SERIAL_4
5035    1           4           8
5040    5

我试图做一个基本上连接同一个表4次的查询,说serial_x不在(其他连续出版物)。这样做的问题是它会产生多个结果:

APPLE   SERIAL_1    SERIAL_2    SERIAL_3    SERIAL_4
5035    1           4           8
5035    1           8           4
5035    4           1           8
5035    4           8           1
5035    8           1           4
5035    4           4           1
5040    5

这显然是因为带有不同序列的apple 5035在表中多次出现,并且它获得了分配给它的三个序列的所有可能组合。我确信有一个简单的方法可以做到这一点,但我已经尝试了很长时间并且无法产生好的结果。有人可以帮忙吗?

5 个答案:

答案 0 :(得分:1)

你可以试试这个,它不优雅但它有效:

SELECT DISTINCT t1.apple, 
    (SELECT serial FROM your_table
     WHERE apple = t1.apple
     ORDER BY serial LIMIT 0,1) serial_1,
    (SELECT serial FROM your_table
     WHERE apple = t1.apple
     ORDER BY serial LIMIT 1,1) serial_2,
    (SELECT serial FROM your_table
     WHERE apple = t1.apple
     ORDER BY serial LIMIT 2,1) serial_3,
    (SELECT serial FROM your_table
     WHERE apple = t1.apple
     ORDER BY serial LIMIT 3,1) serial_4,
    (SELECT serial FROM your_table
     WHERE apple = t1.apple
     ORDER BY serial LIMIT 4,1) serial_5,
    (SELECT serial FROM your_table
     WHERE apple = t1.apple
     ORDER BY serial LIMIT 5,1) serial_6
FROM your_table t1

答案 1 :(得分:0)

您可以尝试使用GROUP_CONCAT聚合函数和GROUP BY APPLE

SELECT 
    a.APPLE,
    GROUP_CONCAT(DISTINCT s.SERIAL) AS serials
FROM 
    apples a
    LEFT JOIN apples s ON s.APPLE = a.APPLE
GROUP BY a.APPLE


在MySQL中测试:

mysql> select * from apples;
+------+-------+--------+
| ID   | APPLE | SERIAL |
+------+-------+--------+
| 2052 |  5035 |      1 |
| 2055 |  5035 |      4 |
| 2058 |  5035 |      8 |
| 2070 |  5040 |      5 |
+------+-------+--------+
4 rows in set (0.00 sec)

mysql> SELECT 
    ->     a.APPLE,
    ->     GROUP_CONCAT(DISTINCT s.SERIAL) AS serials
    -> FROM 
    ->     apples a
    ->     LEFT JOIN apples s ON s.APPLE = a.APPLE
    -> GROUP BY a.APPLE;
+-------+---------+
| APPLE | serials |
+-------+---------+
|  5035 | 1,4,8   |
|  5040 | 5       |
+-------+---------+
2 rows in set (0.00 sec)

mysql> 

答案 2 :(得分:0)

Oracle 11g的LISTAGG function似乎可以满足您的需求。我这里没有11g,但以下内容应该很接近:

SELECT apple, listagg(serial, ',') WITHIN GROUP (ORDER BY serial) "Serial Numbers"
  FROM tbl
 GROUP BY apple;

您没有获得每个序列项的漂亮列标题,但它应该可以正常工作。

答案 3 :(得分:0)

我会做这样的事情:

with data as (
    select 2052 id, 5035 apple, 1 serial from dual union all
    select 2055 id, 5035 apple, 4 serial from dual union all
    select 2058 id, 5035 apple, 8 serial from dual union all
    select 2070 id, 5040 apple, 5 serial from dual
)
select
    apple,
    serial_1,
    serial_2,
    serial_3,
    serial_4,
    serial_5,
    serial_6
from (
    select
        apple,
        serial as serial_1,
        lead(serial,1) over (partition by apple order by serial) as serial_2,
        lead(serial,2) over (partition by apple order by serial) as serial_3,
        lead(serial,3) over (partition by apple order by serial) as serial_4,
        lead(serial,4) over (partition by apple order by serial) as serial_5,
        lead(serial,5) over (partition by apple order by serial) as serial_6,
        row_number() over (partition by apple order by serial) rn
    from data
)
where rn = 1;

显然你不需要WITH块,因为你可以使用你的真实表,所以你的查询将从SELECT开始。

这将提供以下输出:

 APPLE   SERIAL_1   SERIAL_2   SERIAL_3   SERIAL_4   SERIAL_5   SERIAL_6
     
  5035          1          4          8
  5040          5

答案 4 :(得分:0)

游戏有点晚了,但是由于在Oracle中没有使用PIVOT子句的答案,所以它可能会很有趣。

SELECT *
FROM (
  SELECT apple, serial
  FROM fruits
) t
PIVOT ( 
  max(serial) for serial in (1,2,3,4,5,6)
) 

SQLFiddle示例:http://sqlfiddle.com/#!4/3cede/2