2013-09-19 1 views
2

Я пытаюсь выяснить способ идентификации «запуска» результатов (последовательных строк в порядке), которые удовлетворяют некоторому условию. В настоящее время я заказываю результирующий набор и просматриваю отдельные шаблоны. Вот пример:Поиск «запуска» строк из упорядоченного результирующего набора

SELECT the_date, name 
FROM orders 
WHERE 
    the_date BETWEEN 
     to_date('2013-09-18',..) AND 
     to_date('2013-09-22', ..) 
ORDER BY the_date 

-------------------------------------- 
the_date   | name 
-------------------------------------- 
2013-09-18 00:00:01 | John 
-------------------------------------- 
2013-09-19 00:00:01 | James 
-------------------------------------- 
2013-09-20 00:00:01 | John 
-------------------------------------- 
2013-09-20 00:00:02 | John 
-------------------------------------- 
2013-09-20 00:00:03 | John 
-------------------------------------- 
2013-09-20 00:00:04 | John 
-------------------------------------- 
2013-09-21 16:00:01 | Jennifer 
-------------------------------------- 

То, что я хочу, чтобы извлечь из этого результирующего набора является все строки, приписываемые John на 2013-09-20. Вообще то, что я ищу, это запуск результатов из того же name, в строке,> = 3. Я использую Oracle 11, но мне интересно узнать, может ли это быть достигнуто со строгим SQL, или если необходимо использовать некоторую аналитическую функцию.

+0

Не могли бы вы опубликовать ожидаемый результат? Что вы подразумеваете под управлением? – SriniV

+0

@realspirituals Я объяснил ожидаемый результат и то, что я имел в виду под «запуском» результатов. Это было непонятно? –

+0

Посмотрите мое сообщение и подтвердите, что то, что вы ищете ... – SriniV

ответ

3

Вам нужно несколько вложенных функций окна:

SELECT * 
FROM 
(
    SELECT the_date, name, grp, 
     COUNT(*) OVER (PARTITION BY grp) AS cnt 
    FROM 
    (
     SELECT the_date, name, 
     SUM(flag) OVER (ORDER BY the_date) AS grp 
     FROM 
     (
     SELECT the_date, name, 
      CASE WHEN LAG(name) OVER (ORDER BY the_date) = name THEN 0 ELSE 1 END AS flag 
     FROM orders 
     WHERE 
      the_date BETWEEN 
       TO_DATE('2013-09-18',..) AND 
       TO_DATE('2013-09-22', ..) 
     ) dt 
    ) dt 
) dt 
WHERE cnt >= 3 
ORDER BY the_date 
+0

Действительно круто решение. Не знал о функции LAG. Я потрачу некоторое время, действительно знакомясь с «ОВЕР» в ближайшие несколько дней. –

0

Попробуйте

WITH ORDERS 
    AS (SELECT 
      TO_DATE ('2013-09-18 00:00:01', 
        'YYYY-MM-DD HH24:MI:SS') 
       AS THE_DATE, 
      'John' AS NAME 
     FROM 
      DUAL 
     UNION ALL 
     SELECT 
      TO_DATE ('2013-09-19 00:00:01', 
        'YYYY-MM-DD HH24:MI:SS') 
       AS THE_DATE, 
      'James' AS NAME 
     FROM 
      DUAL 
     UNION ALL 
     SELECT 
      TO_DATE ('2013-09-20 00:00:01', 
        'YYYY-MM-DD HH24:MI:SS') 
       AS THE_DATE, 
      'John' AS NAME 
     FROM 
      DUAL 
     UNION ALL 
     SELECT 
      TO_DATE ('2013-09-20 00:00:02', 
        'YYYY-MM-DD HH24:MI:SS') 
       AS THE_DATE, 
      'John' AS NAME 
     FROM 
      DUAL 
     UNION ALL 
     SELECT 
      TO_DATE ('2013-09-20 00:00:03', 
        'YYYY-MM-DD HH24:MI:SS') 
       AS THE_DATE, 
      'John' AS NAME 
     FROM 
      DUAL 
     UNION ALL 
     SELECT 
      TO_DATE ('2013-09-20 00:00:04', 
        'YYYY-MM-DD HH24:MI:SS') 
       AS THE_DATE, 
      'John' AS NAME 
     FROM 
      DUAL 
     UNION ALL 
     SELECT 
      TO_DATE ('2013-09-21 16:00:01', 
        'YYYY-MM-DD HH24:MI:SS') 
       AS THE_DATE, 
      'Jennifer' AS NAME 
     FROM 
      DUAL) 
SELECT 
     B.* 
FROM 
     (SELECT 
      TRUNC (THE_DATE) THE_DATE, 
      NAME, 
      COUNT (*) 
     FROM 
      ORDERS 
     WHERE 
      THE_DATE BETWEEN TRUNC (TO_DATE ('2013-09-18', 
             'YYYY-MM-DD')) 
         AND TRUNC (TO_DATE ('2013-09-22', 
             'YYYY-MM-DD')) 
     GROUP BY 
      TRUNC (THE_DATE), 
      NAME 
     HAVING 
      COUNT (*) >= 3) A, 
     ORDERS B 
WHERE 
     A.NAME = B.NAME 
     AND TRUNC (A.THE_DATE) = TRUNC (B.THE_DATE); 

ВЫВОД

9/20/2013 12:00:01 AM John 
9/20/2013 12:00:02 AM John 
9/20/2013 12:00:03 AM John 
9/20/2013 12:00:04 AM John 
+0

Использование TRUNC оказывает влияние на производительность, если данные огромны. – SriniV

+0

Извините, я не должен был правильно объяснять себя при определении «прогона», и я не представил достаточно хорошего образца данных. То, что я искал, было когда 3 или более рядов появились для всех одним и тем же человеком. Если у Джейн 4 строки в тот же день, но они не в порядке, ее данные не должны возвращаться. Однако я обновлю вопрос. –