sql >> データベース >  >> RDS >> Oracle

列の日付範囲内の各日付に発生する行数をカウントします

    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
    

    更新:

    分析関数を利用した、より優れた高速クエリ。

    主な考え方は、各日付を含む範囲の数は、その日付より前に開始された範囲の数と、その日付より前に終了した範囲の数の差であるということです。

    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
    

    このクエリは1で完了します 1,000,000の2番目 行。

    詳細については、ブログのこのエントリを参照してください:



    1. JDBC結果セットに基づいてテーブルを作成する方法

    2. 結果セットを変数に選択し、同じストアドプロシージャの後で更新でその変数を使用します

    3. トリガー関数で行タイプの動的列名にアクセスします

    4. select SCOPE_IDENTITY()が整数ではなく小数を返すのはなぜですか?