С Oracle SQL как я могу найти 3 дня, где общая сумма> = 150 - PullRequest
0 голосов
/ 18 февраля 2020

У меня есть отчет, в котором нужно перечислить активность, где итоговое значение>> 150 за 3 последовательных дней.
Допустим, я создал временную таблицу foo для суммирования ежедневных итогов.

| ID | Day        | Total |
| -- | ---------- | ----- |
| 01 | 2020-01-01 |   10  |
| 01 | 2020-01-02 |   50  |
| 01 | 2020-01-03 |   50  |
| 01 | 2020-01-04 |   50  |
| 01 | 2020-01-05 |   20  |
| 02 | 2020-01-01 |   10  |
| 02 | 2020-01-02 |   10  |
| 02 | 2020-01-03 |   10  |
| 02 | 2020-01-04 |   10  |
| 02 | 2020-01-05 |   10  |

Как мне написать SQL, чтобы вернуть ID 01, но не 02?

Пример результата:

| ID |
| -- |
| 01 |

Ответы [ 5 ]

4 голосов
/ 18 февраля 2020

Я подозреваю, что вам нужны оконные функции здесь:

select distinct id
from (
    select 
        t.*, 
        sum(total) over(partition by id order by day rows between 2 preceding and current row) sum_total,
        count(*)   over(partition by id order by day rows between 2 preceding and current row) cnt
    from mytable t
) t
where cnt = 3 and sum_total >= 150

Это дает вам id с общим итогом, превышающим заданный порог в течение 3 последовательных дней - что вот как я понял твой вопрос.

1 голос
/ 18 февраля 2020

Если вы просто хотите вывести строки, которые имеют 3 последовательных дня с суммой> = 150, вы можете использовать функцию analyti c, чтобы определить скользящую сумму по каждому 3-дневному периоду для идентификатора, а затем найти агрегат максимальное значение скользящей суммы для идентификатора, возвращая идентификатор, где он> = 150.

Например:

WITH your_table AS (SELECT 1 ID, to_date('01/01/2020', 'dd/mm/yyyy') dy, 10 total FROM dual UNION ALL
                    SELECT 1 ID, to_date('02/01/2020', 'dd/mm/yyyy') dy, 50 total FROM dual UNION ALL
                    SELECT 1 ID, to_date('03/01/2020', 'dd/mm/yyyy') dy, 50 total FROM dual UNION ALL
                    SELECT 1 ID, to_date('04/01/2020', 'dd/mm/yyyy') dy, 50 total FROM dual UNION ALL
                    SELECT 1 ID, to_date('05/01/2020', 'dd/mm/yyyy') dy, 20 total FROM dual UNION ALL
                    SELECT 2 ID, to_date('01/01/2020', 'dd/mm/yyyy') dy, 10 total FROM dual UNION ALL
                    SELECT 2 ID, to_date('02/01/2020', 'dd/mm/yyyy') dy, 10 total FROM dual UNION ALL
                    SELECT 2 ID, to_date('03/01/2020', 'dd/mm/yyyy') dy, 10 total FROM dual UNION ALL
                    SELECT 2 ID, to_date('04/01/2020', 'dd/mm/yyyy') dy, 10 total FROM dual UNION ALL
                    SELECT 2 ID, to_date('05/01/2020', 'dd/mm/yyyy') dy, 10 total FROM dual),
    moving_sums AS (SELECT ID,
                           dy,
                           total,
                           SUM(total) OVER (PARTITION BY ID ORDER BY dy RANGE BETWEEN 2 PRECEDING AND CURRENT ROW) moving_sum
                    FROM   your_table)
SELECT ID
FROM   moving_sums
GROUP BY ID
HAVING MAX(moving_sum) >= 150;

        ID
----------
         1
1 голос
/ 18 февраля 2020

Вы можете использовать HAVING пункт GROUPED BY ID для перечисления желаемых ID значений

SELECT ID
  FROM foo
 GROUP BY ID
HAVING COUNT( distinct day )>=3 AND SUM( NVL(Total,0) ) >= 150

Демо

0 голосов
/ 19 февраля 2020

Используйте это, если хотите указать даты

WITH foo( ID, Day, Total ) AS
(
 SELECT '01', date'2020-01-01' ,   10  FROM dual
 UNION ALL SELECT '01', date'2020-01-02' ,   50  FROM dual
 UNION ALL SELECT '01', date'2020-01-03' ,   50  FROM dual
 UNION ALL SELECT '01', date'2020-01-04' ,   50  FROM dual
 UNION ALL SELECT '01', date'2020-01-05' ,   20  FROM dual
 UNION ALL SELECT '02', date'2020-01-01' ,   10  FROM dual
 UNION ALL SELECT '02', date'2020-01-02' ,   10  FROM dual
 UNION ALL SELECT '02', date'2020-01-03' ,   10  FROM dual
 UNION ALL SELECT '02', date'2020-01-04' ,   10  FROM dual
 UNION ALL SELECT '02', date'2020-01-05' ,   10  FROM dual
)SELECT
    ID
FROM foo
WHERE day BETWEEN TO_DATE('2020-01-01', 'YYYY-MM-DD' ) AND TO_DATE('2020-01-04', 'YYYY-MM-DD' )
GROUP BY ID  HAVING SUM(Total) >= 150;

РЕЗУЛЬТАТ:

ID|
--|
01|
0 голосов
/ 18 февраля 2020

Может быть, вы можете попробовать что-то вроде этого:

SELECT
    *
FROM foo
WHERE day BETWEEN 2020-01-01 AND 2020-01-04
    AND total > 150
...