Oracle — Как выбрать записи на основе приведенной ниже логики?

#sql #oracle

#sql #Oracle

Вопрос:

У меня есть:

  Table A
 -------
 N0       Date        Time
 -----------------------------
 123    20-Apr-11      10:00:05
 123    20-Apr-11      10:00:06
 456    20-Apr-11      10:00:01
 456    20-Apr-11      10:00:02

 Table B
 -------
 N0       Date        Time
 -----------------------------
 123    20-Apr-11      10:00:02
 123    20-Apr-11      10:00:04
 123    20-Apr-11      10:00:05
 123    20-Apr-11      10:00:07
 123    20-Apr-11      10:00:08
 456    20-Apr-11      10:00:04
 456    20-Apr-11      10:00:05
 456    20-Apr-11      10:00:02
 456    20-Apr-11      10:00:03
 456    20-Apr-11      10:00:00
  

Желаемый результат

  A.N0     A.Date       A.Time     B.Time
 ----------------------------------------
 123    20-Apr-11      10:00:05  10:00:07   
 123    20-Apr-11      10:00:06  10:00:08
 456    20-Apr-11      10:00:01  10:00:03
 456    20-Apr-11      10:00:02  10:00:04
  

Примечание

Если вы видите приведенные выше результаты, они B.time должны быть больше A.time и не должны повторяться при объединении.

Пожалуйста, подскажите мне, как это сделать с помощью инструкции oracle SQL.

Комментарии:

1. Почему во второй строке есть 10:00:08 время окончания, а 10:00:07 нет?

2. Привет, потому что 10:00:07 уже выбрано в первой строке.

3. @hansa — Строки неупорядочены. Вторая строка не «знает», что «первая» строка выбрала это время. С точки зрения набора, оба 10:00:05 и 10:00:06 могут совпадать с 10:00:07 и 10:00:08 .

4. И почему A.time 10:00:01 не совпадает с B.time 10:00:02 ?

5. @ypercube Каждый раз B.Время должно отображаться не более одного раза, по-видимому

Ответ №1:

Вот кое-что, что даст вам запрошенный вами результат:

 With NumberedA As
    (
    Select *
        , Row_Number() Over ( Partition By N0, Date Order By Time ) Num
    From TableA
    )
    , NumberedB As
    (
    Select A.N0, A.Date
        , A.Time ATime
        , B.Time BTime
        , Row_Number() Over ( Partition By A.N0, A.Date, A.Time Order By B.Time ) Num
    From TableA A
        Join TableB B
            On B.N0 = A.N0
                And B.Date = A.Date
                And B.Time > A.Time
    )
Select A.N0, A.Date, A.Time, B.Time
From NumberedA A
    Join NumberedB B
        On B.N0 = A.N0
            And B.Date = A.Date
            And B.ATime = A.Time
            And B.Num = A.Num
  

Тем не менее, было бы полезно, если бы мы поняли причину вашего запроса.

Ответ №2:

Проверьте это

Но требуется создать один новый столбец с именем ‘Flag’ в таблице B

 CREATE OR REPLACE PROCEDURE Proc_test
IS
BEGIN
   FOR i IN (SELECT   *
                 FROM a
             ORDER BY NAME, date, time)
   LOOP
      FOR j IN (SELECT   *
                    FROM b
                ORDER BY NAME, date, time)
      LOOP
         IF     i.NAME = j.NAME
            AND i.date = j.date
            AND j.flag IS NULL
            AND i.time < j.time
         THEN
            INSERT INTO target
                        (NAME, date, time1, time2
                        )
                 VALUES (i.NAME, i.date, i.time, j.time
                        );

            UPDATE b
               SET flag = 'Y'
             WHERE NAME = i.NAME AND date = i.date AND time = j.time;

            COMMIT;
         END IF;
      END LOOP;
   END LOOP;
END;
/
  

Он работает нормально….