sql >> Databáze >  >> RDS >> Oracle

počet řádků, které se vyskytují pro každé datum v časovém období sloupců

WITH    q AS
        (
        SELECT  (
                SELECT  MIN(start_date)
                FROM    mytable
                ) + level - 1 AS mydate
        FROM    dual
        CONNECT BY
                level <= (
                SELECT  MAX(end_date) - MIN(start_date)
                FROM    mytable
                )
        )
SELECT  group, mydate,
        (
        SELECT  COUNT(*)
        FROM    mytable mi
        WHERE   mi.group = mo.group
                AND q BETWEEN mi.start_date AND mi.end_date
        ) 
FROM    q
CROSS JOIN
        (
        SELECT  DISTINCT group
        FROM    mytable
        ) mo

Aktualizace:

Lepší a rychlejší dotaz využívající analytické funkce.

Hlavní myšlenkou je, že počet rozsahů obsahujících každé datum je rozdíl mezi počtem rozsahů zahájených před tímto datem a počtem rozsahů, které skončily před tímto datem.

SELECT  cur_date,
        grouper,
        SUM(COALESCE(scnt, 0) - COALESCE(ecnt, 0)) OVER (PARTITION BY grouper ORDER BY cur_date) AS ranges
FROM    (
        SELECT  (
                SELECT  MIN(start_date)
                FROM    t_range
                ) + level - 1 AS cur_date
        FROM    dual
        CONNECT BY
                level <=
                (
                SELECT  MAX(end_date)
                FROM    t_range
                ) -
                (
                SELECT  MIN(start_date)
                FROM    t_range
                ) + 1
        ) dates
CROSS JOIN
        (
        SELECT  DISTINCT grouper AS grouper
        FROM    t_range
        ) groups
LEFT JOIN
        (
        SELECT  grouper AS sgrp, start_date, COUNT(*) AS scnt
        FROM    t_range
        GROUP BY
                grouper, start_date
        ) starts
ON      sgrp = grouper
        AND start_date = cur_date
LEFT JOIN
        (
        SELECT  grouper AS egrp, end_date, COUNT(*) AS ecnt
        FROM    t_range
        GROUP BY
                grouper, end_date
        ) ends
ON      egrp = grouper
        AND end_date = cur_date - 1
ORDER BY
        grouper, cur_date

Tento dotaz se dokončí za 1 sekundu na 1,000,000 řádky.

Další podrobnosti najdete v tomto příspěvku na mém blogu:



  1. Mysql Vypočítat časový rozdíl mezi časovými razítky ve stejném poli?

  2. Jak spustit stejný dotaz proti více tabulkám v databázi

  3. Jak mohu použít alias v klauzuli where?

  4. Vložte sadu dat do tabulky Oracle