我需要在符合某个标准的情况下将一条记录拆分为2条,并且在将它们拆分后很难将它们连接在一起。 我有这张桌子:
对于那天的会议,我需要将它们分成两个会话,一个在早上,一个在下午。在这个例子中,我需要将测试2分成2个会话AM和PM。
我已经使用了这个陈述,它很适合我:
WITH DATA
AS
(SELECT
CASE
WHEN level=1 THEN 'AM'
WHEN LEVEL=2 THEN 'PM'
END "Session"
FROM dual CONNECT BY level<3)
SELECT "Meeting","From","EndTime","StartTime","Session"
FROM "TEST", DATA
WHERE ("StartTime" < 12 AND "StartTime">=8) AND ( "EndTime" > 12 AND "EndTime" <= 17)
然而,当我试图结合上半天的另一次会议时,我收到了以下错误:
ORA-32034: unsupported use of WITH clause
32034. 00000 - "unsupported use of WITH clause"
*Cause: Inproper use of WITH clause because one of the following two reasons
1. nesting of WITH clause within WITH clause not supported yet
2. For a set query, WITH clause can't be specified for a branch.
3. WITH clause can't sepecified within parentheses.
*Action: correct query and retry
Error at Line: 56 Column: 1
这是我使用的sql语句:
SELECT *
FROM
(
SELECT "Meeting","From","EndTime","StartTime" ,
CASE
WHEN "StartTime" >= 8 AND "EndTime" <= 12 THEN 'AM'
WHEN "StartTime" >= 12 AND "EndTime" <= 17 THEN 'PM'
ELSE 'UNKNOWN'
END "Session"
FROM "TEST"
WHERE ("StartTime" >= 8 AND "EndTime" <= 12)
OR
("StartTime" >= 12 AND "EndTime" <= 17)
) HalfDay
UNION ALL
(
WITH DATA
AS
(SELECT
CASE
WHEN level=1 THEN 'AM'
WHEN LEVEL=2 THEN 'PM'
END "Session"
FROM dual CONNECT BY level<3)
SELECT "Meeting","From","EndTime","StartTime","Session"
FROM "TEST", DATA
WHERE ("StartTime" < 12 AND "StartTime">=8) AND ( "EndTime" > 12 AND "EndTime" <= 17)
) FullDay
我该如何解决这个问题? 请查找附带的脚本以创建表格和相关数据。
CREATE TABLE "TEST"
( "Meeting" VARCHAR2(20 BYTE),
"From" DATE,
"StartTime" NUMBER,
"EndTime" NUMBER
) ;
Insert into TEST ("Meeting","From","StartTime","EndTime") values ('Test 1',to_date('06-JUL-15','DD-MON-RR'),12,17);
Insert into TEST ("Meeting","From","StartTime","EndTime") values ('Test 2',to_date('12-DEC-15','DD-MON-RR'),8,17);
我的目标是获得此输出
以及这个一对一视图
答案 0 :(得分:2)
你并没有真正用两个子句嵌套,但是你在一个联盟中嵌套一个。
with
子句声明一个或多个子查询,并为它们分配一个可在查询中进一步使用的名称,如视图。
这就是你在这里可以做的事情。将整个with
子句及其定义的内联视图移动到顶部。之后,工会部分紧随其后。经过一点清理后,它看起来像这样:
WITH
DATA AS
(SELECT
CASE
WHEN level=1 THEN 'AM'
WHEN LEVEL=2 THEN 'PM'
END "Session"
FROM dual CONNECT BY level < 3)
SELECT "Meeting","From","EndTime","StartTime" ,
CASE
WHEN "StartTime" >= 8 AND "EndTime" <= 12 THEN 'AM'
WHEN "StartTime" >= 12 AND "EndTime" <= 17 THEN 'PM'
ELSE 'UNKNOWN'
END "Session"
FROM "TEST"
WHERE ("StartTime" >= 8 AND "EndTime" <= 12)
OR
("StartTime" >= 12 AND "EndTime" <= 17)
UNION ALL
SELECT "Meeting", "From", "EndTime", "StartTime", "Session"
FROM "TEST", DATA
WHERE
"StartTime" < 12 AND "StartTime" >= 8 AND
"EndTime" > 12 AND "EndTime" <= 17
没有WITH
的同一查询:
SELECT "Meeting","From","EndTime","StartTime" ,
CASE
WHEN "StartTime" >= 8 AND "EndTime" <= 12 THEN 'AM'
WHEN "StartTime" >= 12 AND "EndTime" <= 17 THEN 'PM'
ELSE 'UNKNOWN'
END "Session"
FROM "TEST"
WHERE ("StartTime" >= 8 AND "EndTime" <= 12)
OR
("StartTime" >= 12 AND "EndTime" <= 17)
UNION ALL
SELECT "Meeting", "From", "EndTime", "StartTime", "Session"
FROM
"TEST",
(SELECT
CASE
WHEN level=1 THEN 'AM'
WHEN LEVEL=2 THEN 'PM'
END "Session"
FROM dual CONNECT BY level < 3)
WHERE
"StartTime" < 12 AND "StartTime" >= 8 AND
"EndTime" > 12 AND "EndTime" <= 17
答案 1 :(得分:1)
使用两个子查询(省略联合)的更紧凑的解决方案。 映射表的第一个,提供一对一的连接或两个记录中的拆分。 第二个子查询转换您的日期源,添加“持续时间”键,表示 树案例:仅AM,仅PM或AM + PM 其余的是一个简单的连接。
with join_helper as (
select 'AM' "Duration", 'AM' "Session" from dual union all
select 'PM' "Duration", 'PM' "Session" from dual union all
select 'AM-PM' "Duration", 'AM' "Session" from dual union all
select 'AM-PM' "Duration", 'PM' "Session" from dual),
session_duration as (
select test.*,
CASE
WHEN "StartTime" < 12 AND "EndTime" >= 12 THEN 'AM-PM'
WHEN "StartTime" < 12 THEN 'AM'
WHEN "EndTime" >= 12 THEN 'PM'
END "Duration"
from test)
select a."Meeting", a."From",a."StartTime",a."EndTime", b."Session"
from session_duration a, join_helper b
where a."Duration" = b."Duration"
;
你可能会发现查询中的逻辑分散了..
答案 2 :(得分:1)
SELECT "Meeting","From","EndTime","StartTime" ,
CASE
WHEN "StartTime" >= 8 THEN 'AM'
END "Session"
FROM "TEST"
union all
SELECT "Meeting","From","EndTime","StartTime" ,
CASE
WHEN "EndTime" <= 17 THEN 'PM'
END "Session"
FROM "TEST"
where "StartTime" <12 AND "EndTime" <= 17 ;