Sql 基于同一表上的值在同一行上返回多个值
我已经有一段时间被难住了,一直在尝试根据其他结果从我们的一个表中获取结果,并且每个值都不返回多行,这很难为我解释,所以我将给出一个示例 我们有一个价值观,例如苹果。每个苹果都有自己的序列号,serial。对于某些苹果,有多个(最多6个)序列值Sql 基于同一表上的值在同一行上返回多个值,sql,oracle,pivot,Sql,Oracle,Pivot,我已经有一段时间被难住了,一直在尝试根据其他结果从我们的一个表中获取结果,并且每个值都不返回多行,这很难为我解释,所以我将给出一个示例 我们有一个价值观,例如苹果。每个苹果都有自己的序列号,serial。对于某些苹果,有多个(最多6个)序列值 ID APPLE SERIAL 2052 5035 1 2055 5035 4 2058 5035 8 2070 5040 5 在我的结果中,我想返回每
ID APPLE SERIAL
2052 5035 1
2055 5035 4
2058 5035 8
2070 5040 5
在我的结果中,我想返回每个苹果一次,以及分配给它的所有序列号,例如:
APPLE SERIAL_1 SERIAL_2 SERIAL_3 SERIAL_4
5035 1 4 8
5040 5
我试着做了一个查询,它基本上连接了同一个表4次,说serial_x not in(其他serial)。这样做的问题是,它会产生如下多种结果:
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
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;
这显然是因为具有不同序列的apple 5035在表中多次出现,并且它获得分配给它的三个序列的所有可能组合。我相信有一个简单的方法可以做到这一点,但我已经尝试了很长时间,并没有能够产生一个好的结果。有人能帮忙吗?你可以试试这个,它不雅致,但很管用:
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
你可以试试这个,它不雅致,但很管用:
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
您可以尝试使用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>
您可以尝试使用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>
甲骨文11g有一个功能,似乎可以满足您的需求。我这里没有11g,但下面应该很接近:
SELECT apple, listagg(serial, ',') WITHIN GROUP (ORDER BY serial) "Serial Numbers"
FROM tbl
GROUP BY apple;
您无法为每个序列项获得良好的列标题,但它应该可以工作。Oracle11g具有的功能似乎可以满足您的需要。我这里没有11g,但下面应该很接近:
SELECT apple, listagg(serial, ',') WITHIN GROUP (ORDER BY serial) "Serial Numbers"
FROM tbl
GROUP BY apple;
您无法为每个序列项获得良好的列标题,但它应该可以工作。我会这样做:
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
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
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
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开始
这将产生以下输出:
游戏进行得有点晚,但由于在Oracle中没有使用PIVOT子句的答案,因此可能会很有趣
SELECT *
FROM (
SELECT apple, serial
FROM fruits
) t
PIVOT (
max(serial) for serial in (1,2,3,4,5,6)
)
SQLFiddle示例:游戏进行得有点晚,但由于在Oracle中没有使用PIVOT子句的答案,因此可能会很有趣
SELECT *
FROM (
SELECT apple, serial
FROM fruits
) t
PIVOT (
max(serial) for serial in (1,2,3,4,5,6)
)
SQLFiddle示例:在SQL Server上,您可以使用PIVOT函数。我不确定MySql和Oracle中是否存在PIVOT。Oracle中有PIVOT函数。在SQL Server上,您可以使用PIVOT函数。我不确定MySql和Oracle中是否存在PIVOT。Oracle中有PIVOT函数。@Marco我没有,但由于担心它不起作用,我只是尝试了一下,结果成功了。看看我在答案后面附加了什么。嘿,就像上面的解决方案一样,GROUP_CONCAT函数不适用于Oracle,同样,我应该在最初的帖子中说我正在使用Oracle。无论如何,应该有一个甲骨文的等价物,我会研究一下。谢谢:)@Jamie Joe是的[mysql]标签有误导性。我试图从问题中确定您使用的是MySQL还是Oracle,但无法确定。关于Oracle中的GROUP_CONCAT,也许可以提供帮助?它不起作用:OP希望每个序列都在不同的列中,而不是一列序列都已连接@Marco它正在工作,但是它没有将序列分成单独的列。我建议OP可以尝试在查询之外进行分离。。但我的答案似乎对OP没有多大用处,因为他需要Oracle的解决方案。@Marco我没有,但因为担心它不起作用,我只是尝试了一下,它起了作用。看看我在答案后面附加了什么。嘿,就像上面的解决方案一样,GROUP_CONCAT函数不适用于Oracle,同样,我应该在最初的帖子中说我正在使用Oracle。无论如何,应该有一个甲骨文的等价物,我会研究一下。谢谢:)@Jamie Joe是的[mysql]标签有误导性。我试图从问题中确定您使用的是MySQL还是Oracle,但无法确定。关于Oracle中的GROUP_CONCAT,也许可以提供帮助?它不起作用:OP希望每个序列都在不同的列中,而不是一列序列都已连接@Marco它正在工作,但是它没有将序列分成单独的列。我建议OP可以尝试在查询之外进行分离。。但我的答案对OP来说似乎不是很有用,因为他需要一个针对Oracle的解决方案。嘿,极限函数不适用于Oracle,也许我应该在我使用Oracle的帖子中提到。无论如何,我会用谷歌搜索到oracle的LIMIT。感谢您的快速回复@JamieJoe:你应该检查你的标签:如果你在使用Oracle,为什么要放MySql?嘿,LIMIT函数不适用于Oracle,也许我应该在帖子中提到我在使用Oracle。无论如何,我会用谷歌搜索到oracle的LIMIT。感谢您的快速回复@JamieJoe:你应该检查一下你的标签:如果你在使用Oracle,为什么要放MySql?太好了,正是我需要的。非常感谢你!现在是学习代码的时候了:)太好了,正是我所需要的。非常感谢你!现在是学习代码的时候了:)