как удалить коррелированный подзапрос - PullRequest
0 голосов
/ 28 ноября 2011

Я бы хотел переписать этот запрос, чтобы не использовать коррелированный подзапрос, но добиться того же результата запроса.

CREATE TABLE "TABLE_1" 
(   "SITE_ID" NUMBER(*,0), 
"USER_ID" NUMBER(*,0), 
"REC_ID" NUMBER, 
"REPORT_DATE" DATE
) ;

CREATE TABLE "TABLE_2" 
(   "SITE_ID" NUMBER, 
"NOTE_DATE" DATE, 
"NOTES" VARCHAR2(2000 BYTE), 
"USER_ID" NUMBER, 
"REC_ID" NUMBER
) ;

CREATE TABLE "TABLE_3" 
(   "SITE_ID" NUMBER, 
"NOTE_DATE" DATE, 
"HELP_NOTES" VARCHAR2(2000 BYTE), 
"USER_ID" NUMBER, 
"REC_ID" NUMBER
) ;

REM INSERTING into TABLE_1
Insert into TABLE_1 (SITE_ID,USER_ID,REC_ID,REPORT_DATE) values (1,6165,121,to_date('17-APR-10','DD-MON-RR'));
Insert into TABLE_1 (SITE_ID,USER_ID,REC_ID,REPORT_DATE) values (1,6165,121,to_date('01-MAY-10','DD-MON-RR'));
Insert into TABLE_1 (SITE_ID,USER_ID,REC_ID,REPORT_DATE) values (1,6165,121,to_date('08-MAY-10','DD-MON-RR'));
Insert into TABLE_1 (SITE_ID,USER_ID,REC_ID,REPORT_DATE) values (1,6165,121,to_date('24-APR-10','DD-MON-RR'));
Insert into TABLE_1 (SITE_ID,USER_ID,REC_ID,REPORT_DATE) values (1,6165,121,to_date('15-MAY-10','DD-MON-RR'));
Insert into TABLE_1 (SITE_ID,USER_ID,REC_ID,REPORT_DATE) values (1,6165,121,to_date('05-JUN-10','DD-MON-RR'));
Insert into TABLE_1 (SITE_ID,USER_ID,REC_ID,REPORT_DATE) values (1,6165,121,to_date('22-MAY-10','DD-MON-RR'));
Insert into TABLE_1 (SITE_ID,USER_ID,REC_ID,REPORT_DATE) values (1,6165,121,to_date('29-MAY-10','DD-MON-RR'));

REM INSERTING into TABLE_2
Insert into TABLE_2 (SITE_ID,NOTE_DATE,NOTES,USER_ID,REC_ID) values (1,to_date('13-APR-10','DD-MON-RR'),'Notes - we need stuff.',6165,121);

REM INSERTING into TABLE_3
Insert into TABLE_3 (SITE_ID,NOTE_DATE,HELP_NOTES,USER_ID,REC_ID) values (1,to_date('17-MAY-10','DD-MON-RR'),'Entry #1',1932,121);
Insert into TABLE_3 (SITE_ID,NOTE_DATE,HELP_NOTES,USER_ID,REC_ID) values (1,to_date('12-MAY-10','DD-MON-RR'),'Entry #2',6005,121);
Insert into TABLE_3 (SITE_ID,NOTE_DATE,HELP_NOTES,USER_ID,REC_ID) values (1,to_date('25-MAY-10','DD-MON-RR'),'Entry #3',1932,121);

ALTER TABLE "TABLE_1" MODIFY ("REC_ID" NOT NULL ENABLE);
--------------------------------------------------------
--  Constraints for Table TABLE_2
--------------------------------------------------------

  ALTER TABLE "TABLE_2" MODIFY ("SITE_ID" NOT NULL ENABLE);

  ALTER TABLE "TABLE_2" MODIFY ("REC_ID" NOT NULL ENABLE);
--------------------------------------------------------
--  Constraints for Table TABLE_3
--------------------------------------------------------

  ALTER TABLE "TABLE_3" MODIFY ("SITE_ID" NOT NULL ENABLE);

  ALTER TABLE "TABLE_3" MODIFY ("REC_ID" NOT NULL ENABLE);

Запрос выглядит следующим образом:

SELECT
TABLE_1.REC_ID,
TO_CHAR(table_1.REPORT_DATE, 'DD-MON-YY HH:MI:SS') report_date,
(
  SELECT
    MAX(table_3.NOTE_DATE) AS MAX_DATE
  FROM
    table_3
  WHERE
    table_3.REC_ID       = table_1.REC_ID
  AND table_3.NOTE_DATE <= table_1.REPORT_DATE
)
notes_max_date
FROM
table_1
ORDER BY
To_date(table_1.REPORT_DATE, 'DD-MON-YY HH:MI:SS')

И выходные данные должны быть следующими:

REC_ID                 REPORT_DATE        NOTES_MAX_DATE            
---------------------- ------------------ ------------------------- 
121                    17-APR-10 12:30:00                           
121                    24-APR-10 12:30:00                           
121                    01-MAY-10 12:30:00                           
121                    08-MAY-10 12:30:00                           
121                    15-MAY-10 12:30:00 12-MAY-10                 
121                    22-MAY-10 12:30:01 17-MAY-10                 
121                    29-MAY-10 12:30:01 25-MAY-10                 
121                    05-JUN-10 12:30:00 25-MAY-10                 
 8 rows selected 

Выходные данные должны быть 8 строк и включать нули в столбец NOTES_MAX_DATE.Спасибо!

1 Ответ

2 голосов
/ 29 ноября 2011

Вы можете переписать его с LEFT JOIN и GROUP BY следующим образом:

SELECT t1.REC_ID
      ,to_char(t1.REPORT_DATE, 'DD-MON-YY HH:MI:SS') AS report_date
      ,max(t3.NOTE_DATE) AS notes_max_date
FROM   table_1 AS t1
LEFT   JOIN table_3 AS t3 ON t3.REC_ID = t1.REC_ID
                         AND t3.NOTE_DATE <= t1.REPORT_DATE
GROUP  BY t1.REC_ID
      ,to_char(t1.REPORT_DATE, 'DD-MON-YY HH:MI:SS')
ORDER  BY to_date(t1.REPORT_DATE, 'DD-MON-YY HH:MI:SS')
...