2015-07-06 4 views
0

У меня есть необходимость разделить одну запись на 2, когда они соответствуют определенным критериям, и мне сложно объединить их вместе, разделив их. У меня есть эта таблица:Oracle Nesting With Clauses

enter image description here

Для встреч, в день, мне нужно разделить их на 2 сессии, один утром и один во второй половине дня. В этом примере мне нужно разделить тест 2 на 2 сеанса AM и PM.

enter image description here

Я использовал это заявление, и это служит мне хорошо:

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); 

Моя цель получает этот выход

enter image description here

наряду с этим в 1 зрения

enter image description here

ответ

1

Вы на самом деле не гнездятся на спецификаторах, но вы сделайте гнездо внутри объединения.

Статья 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 
+0

Got команда SQL не должным образом закончилось ... Даже если он работал, перемещаясь с помощью к началу изменяет семантику SQL ,Я только хотел добавить AM и PM в записи, имеющие 2 сеанса. – user1205746

+0

Это не изменяет семантику SQL. Вы можете видеть 'DATA' как представление, используемое в другой части запроса, оно может быть даже фактическим видом вне вашего запроса. Кроме того, вы можете пропустить всю часть 'with' и поместить подзаголовок в место, где вы теперь используете' DATA'. – GolezTrol

+0

Работает вся часть sql части, содержащая инструкцию using! Спасибо! – user1205746

1

Немного более компактное решение с использованием двух подзапросов (ommitning союза). Первый для таблицы сопоставления, обеспечивающий объединение либо один к одному, либо разделение на две записи. Второй подзапрос преобразует источник даты, добавляя ключ «Длительность», который представляет дерева: только 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" 
; 

Вы можете найти логику менее рассеянное в запросе ..

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 ;