假设我有一个包含以下数据的表:
+----------+-----+--------+
| CLASS_ID | Day | Period |
+----------+-----+--------+
| 1 | A | CCR |
+----------+-----+--------+
| 1 | B | CCR |
+----------+-----+--------+
| 2 | A | 1 |
+----------+-----+--------+
| 2 | A | 2 |
+----------+-----+--------+
| 3 | A | 3 |
+----------+-----+--------+
| 3 | B | 4 |
+----------+-----+--------+
| 4 | A | 5 |
+----------+-----+--------+
正如您可能从数据的性质中猜测的那样,我正在研究从学生信息系统中提取课程安排数据的Oracle SQL查询。我试图将一个类"期间表达式",一个包含Day
和Period
字段的计算值放入单个字段中。让我们首先考虑我的期望:
GROUP BY
字段,Day
应为聚合字段(通过LISTAGG
函数),因此计算字段为{{1 }} CCR (A-B)
字段,GROUP BY
应为聚合字段,因此计算字段为Period
我只知道如何单独执行每个1-2 (A)
,类似于GROUP BY
匹配的地方:
Day
,反之亦然,匹配SELECT
day,
LISTAGG(period, '-') WITHIN GROUP (ORDER BY period)
FROM schedule
GROUP BY day
,但我没有看到我如何动态地为Periods
和 Period
做同样的事情。查询。
您还会注意到示例数据集中的最后一行不会跨越多天或多个时段,因此我还需要考虑不需要{{1}的课程毕竟。
修改
最终结果应为:
Day
答案 0 :(得分:1)
如何与having count(*) = 1
结合?
select LISTAGG(period, '-') list WITHIN GROUP (ORDER BY period)
from schedule
group by CLASS_ID, day
having count(*) = 1
union all
select LISTAGG(day, '-') list WITHIN GROUP (ORDER BY day)
from schedule
group by CLASS_ID, period
having count(*) = 1
答案 1 :(得分:1)
我真的不清楚为什么要以这种方式输出。它没有提供任何有用的信息(我不认为) - 你无法分辨,例如class_id = 3
,实际使用了哪些日期和时期的组合。有四种可能的组合(根据输出),但实际上只有两种组合在课程表中。
无论如何 - 你可能有你的理由。这是你如何做到的。您似乎想要LISTAGG
和day
period
(均由class_id
分组,它们不会相互分组)。困难在于您只需要聚合列表中的不同值 - 没有重复。因此,您需要select distinct
,分别为period
和day
,然后是列表聚合,然后在内部联接中连接结果。
这样的事情:
with
test_data ( class_id, day, period ) as (
select 1, 'A', 'CCR' from dual union all
select 1, 'B', 'CCR' from dual union all
select 2, 'A', '1' from dual union all
select 2, 'A', '2' from dual union all
select 3, 'A', '3' from dual union all
select 3, 'B', '4' from dual union all
select 4, 'A', '5' from dual
)
-- end of test data; the actual solution (SQL query) begins below this line
select a.class_id, a.list_per || '(' || b.list_day || ')' as expression
from ( select class_id,
listagg(period, '-') within group (order by period) as list_per
from ( select distinct class_id, period from test_data )
group by class_id
) a
inner join
( select class_id,
listagg(day, '-') within group (order by day) as list_day
from ( select distinct class_id, day from test_data )
group by class_id
) b
on a.class_id = b.class_id
;
CLASS_ID EXPRESSION
-------- ----------
1 CCR(A-B)
2 1-2(A)
3 3-4(A-B)
4 5(A)