[英]Oracle 10g: aggregation
Got the following tables: 得到了下表:
Table T 表T
DATE_A | DATE_B | ERRCODE
----------+-----------+--------
01/MAY/13 | 01/JUN/15 | X
01/DEC/17 | 01/FEB/18 | Y
Table U 表U
ERRCODE | ERRDESC
--------+-------------------------------------------
X | Conflicting from : {1} and to Period : {2}
Y | Periods : {1} and {2} overlap
The following code: 如下代码:
select period, wm_concat(errcode) as issues
from ((select DATE_A as period, errcode from T where DATE_A is not null) union all
(select DATE_B, errcode from T where DATE_B is not null)
) di
group by period
order by period;
will transform the Table T
as follow: 将
Table T
转换如下:
PERIOD | ISSUES
----------+--------
01/MAY/13 | X
01/JUN/15 | X
01/DEC/17 | Y
01/FEB/18 | Y
I would like to transform the code above so that: 我想转换上面的代码,以便:
T
with the corresponding ERRDESC
from table U
T
中的ERRDESC
为表U
的相应ERRDESC
{1}
and {2}
in ERRDESC with respectively DATE_A
and DATE_B
{1}
和{2}
分别DATE_A
为DATE_A
和DATE_B
Table V
Table V
So I tried this: 所以我尝试了这个:
INSERT INTO v (
period,
issues
)
SELECT
period,
wm_concat(issue) AS issues
FROM
(
SELECT
t.date_a AS period,
replace( (
SELECT
u.errdesc AS issue
FROM
u
WHERE
t.errcode = u.errcode
),'{1}', t.date_a) AS issue
FROM
t
WHERE
t.date_a IS NOT NULL
UNION ALL
SELECT
t.date_b,
replace( (
SELECT
u.errdesc AS issue
FROM
u
WHERE
t.errcode = u.errcode
),'{2}', t.date_b)
FROM
t
WHERE
t.date_b IS NOT NULL
) di
GROUP BY
period;
But I'm getting this ( Table V
): 但是我得到这个(
Table V
):
PERIOD | ISSUES
----------+--------
01/MAY/13 | Conflicting from : 01/MAY/13 and to Period : {2}
01/JUN/15 | Conflicting from : {1} and to Period : 01/JUN/15
01/DEC/17 | Periods : 01/DEC/17 and {2} overlap
01/FEB/18 | Periods : {1} and 01/FEB/18 overlap
Instead of the result I'm looking for ( Table V
): 我要寻找的不是结果(
Table V
):
PERIOD | ISSUES
----------+--------
01/MAY/13 | Conflicting from : 01/MAY/13 and to Period : 01/JUN/15
01/JUN/15 | Conflicting from : 01/MAY/13 and to Period : 01/JUN/15
01/DEC/17 | Periods : 01/DEC/17 and 01/FEB/18 overlap
01/FEB/18 | Periods : 01/DEC/17 and 01/FEB/18 overlap
The reason being that the select before the union all don't know about date_b
and the select after don't know about date_a
. 原因是联合之前的选择都不知道
date_b
和之后的选择都不知道date_a
。
Question 题
How should modify the latest code to get the expected result ? 如何修改最新代码以获得预期结果?
Note 注意
CREATE TABLE T
(
"DATE_A" DATE,
"DATE_B" DATE,
"ERRCODE" VARCHAR2(2)
) ;
Insert into T (DATE_A,DATE_B,ERRCODE) values (to_date('01/MAY/13','DD/MON/RR'),to_date('01/JUN/15','DD/MON/RR'),'X');
Insert into T (DATE_A,DATE_B,ERRCODE) values (to_date('01/DEC/17','DD/MON/RR'),to_date('01/FEB/18','DD/MON/RR'),'Y');
CREATE TABLE U
(
"ERRCODE" VARCHAR2(2),
"ERRDESC" VARCHAR2(100)
) ;
Insert into U (ERRCODE, ERRDESC) values ('X','Conflicting from : {1} and to Period : {2}');
Insert into U (ERRCODE, ERRDESC) values ('Y','Periods : {1} and {2} overlap');
CREATE TABLE V
(
"PERIOD" DATE,
"ISSUES" VARCHAR2(100)
) ;
commit;
The way I'd do it is to first join the two tables and populate the values in the error description column, then split that into two rows, like so: 我要做的方法是先将两个表连接起来,然后在错误描述列中填充值,然后将其分成两行,如下所示:
INSERT INTO v (period, issues)
WITH t AS (SELECT to_date('01/05/2013', 'dd/mm/yyyy') date_a, to_date('01/06/2015', 'dd/mm/yyyy') date_b, 'X' errcode FROM dual UNION ALL
SELECT to_date('01/12/2017', 'dd/mm/yyyy') date_a, to_date('01/02/2018', 'dd/mm/yyyy') date_b, 'Y' errcode FROM dual),
u AS (SELECT 'X' errcode, 'Conflicting from : {1} and to Period : {2}' errdesc FROM dual UNION ALL
SELECT 'Y' errcode, 'Periods : {1} and {2} overlap' errdesc FROM dual),
dummy AS (SELECT LEVEL rn FROM dual CONNECT BY LEVEL <= 2),
res AS (SELECT t.date_a,
t.date_b,
REPLACE(REPLACE(u.errdesc, '{1}', to_char(t.date_a, 'dd/MON/yyyy', 'nls_date_language = english')), '{2}', to_char(t.date_b, 'dd/MON/yyyy', 'nls_date_language = english')) errdesc
FROM t
INNER JOIN u ON t.errcode = u.errcode)
SELECT CASE WHEN d.rn = 1 THEN res.date_a
WHEN d.rn = 2 THEN res.date_b
END period,
errdesc
FROM res
CROSS JOIN dummy d
ORDER BY res.date_a, d.rn;
PERIOD ERRDESC
----------- --------------------------------------------------------------------------------
01/05/2013 Conflicting from : 01/MAY/2013 and to Period : 01/JUN/2015
01/06/2015 Conflicting from : 01/MAY/2013 and to Period : 01/JUN/2015
01/12/2017 Periods : 01/DEC/2017 and 01/FEB/2018 overlap
01/02/2018 Periods : 01/DEC/2017 and 01/FEB/2018 overlap
This is a kind of unpivot; 这是一种坚定的态度。 if you were in 11g or above, you'd be able to take advantage of the
UNPIVOT
command to split the rows out into two. 如果您使用的是11g或更高版本,则可以利用
UNPIVOT
命令将行分成两部分。 It works by creating a dummy subquery that contains the required amount of rows you want to output for each of your input rows - in your case, that's 2. 它通过创建一个虚拟子查询来工作,该子查询包含要为每个输入行输出的所需行数-在您的情况下为2。
Then we can cross join that to the main result set, meaning that the rows are duplicated. 然后,我们可以将其交叉连接到主要结果集,这意味着这些行是重复的。 Then it's just a matter of working out which columns to show on each row, and voila!
然后,只需确定要在每行上显示哪些列,瞧!
Just a couple of notes about the dates: 关于日期的几点注意事项:
Got it work with the simple solution (below): 通过简单的解决方案(如下)可以工作:
INSERT INTO v (
period,
issues
)
SELECT
period,
wm_concat(issue) AS issues
FROM
(
SELECT
date_a AS period,
replace(replace( (
SELECT
u.errdesc AS issue
FROM
u
WHERE
t.errcode = u.errcode
),'{1}',t.date_a),'{2}',t.date_b) AS issue
FROM
t
WHERE
date_a IS NOT NULL
UNION ALL
SELECT
date_b,
replace(replace( (
SELECT
u.errdesc AS issue
FROM
u
WHERE
t.errcode = u.errcode
),'{1}',t.date_a),'{2}',t.date_b)
FROM
t
WHERE
date_b IS NOT NULL
) di
GROUP BY
period;
EDIT: 编辑:
The solution of Boneist is however better. 但是,Boneist的解决方案更好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.