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

1か月の合計使用日数を確認するにはどうすればよいですか?

    テストデータ

    CREATE TABLE your_table ( usr, start_date, end_date ) AS (
      SELECT 'A', DATE '2017-06-01', DATE '2017-06-03' FROM DUAL UNION ALL
      SELECT 'B', DATE '2017-06-02', DATE '2017-06-04' FROM DUAL UNION ALL -- Overlaps previous
      SELECT 'C', DATE '2017-06-06', DATE '2017-06-06' FROM DUAL UNION ALL
      SELECT 'D', DATE '2017-06-07', DATE '2017-06-07' FROM DUAL UNION ALL -- Adjacent to previous
      SELECT 'E', DATE '2017-06-11', DATE '2017-06-20' FROM DUAL UNION ALL
      SELECT 'F', DATE '2017-06-14', DATE '2017-06-15' FROM DUAL UNION ALL -- Within previous
      SELECT 'G', DATE '2017-06-22', DATE '2017-06-25' FROM DUAL UNION ALL
      SELECT 'H', DATE '2017-06-24', DATE '2017-06-28' FROM DUAL UNION ALL -- Overlaps previous and next
      SELECT 'I', DATE '2017-06-27', DATE '2017-06-30' FROM DUAL UNION ALL
      SELECT 'J', DATE '2017-06-27', DATE '2017-06-28' FROM DUAL;          -- Within H and I          
    

    クエリ

    SELECT SUM( days ) AS total_days
    FROM   (
      SELECT dt - LAG( dt ) OVER ( ORDER BY dt ) + 1 AS days,
             start_end
      FROM   (
        SELECT dt,
               CASE SUM( value ) OVER ( ORDER BY dt ASC, value DESC, ROWNUM ) * value
                 WHEN 1 THEN 'start'
                 WHEN 0 THEN 'end'
               END AS start_end
        FROM   your_table
        UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )
      )
      WHERE start_end IS NOT NULL
    )
    WHERE start_end = 'end';
    

    出力

    TOTAL_DAYS
    ----------
            25
    

    説明

    SELECT dt, value
    FROM   your_table
    UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )
    

    これにより、UNPIVOT 開始日と終了日が同じ列になるようにテーブルを作成します(dt )そして、開始日には+1、終了日には-1の対応する値が与えられます。

    SELECT dt,
           SUM( value ) OVER ( ORDER BY dt ASC, value DESC, ROWNUM ) AS total,
           value
    FROM   your_table
    UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )
    

    開始日と終了日、およびそれらの生成された値の累積合計を示します。範囲の開始には常にvalue=1があります およびtotal=1 範囲の終わりには常にtotal=0があります 。日付が範囲の途中である場合は、total>1のいずれかになります。 またはvalue=-1 およびtotal=1 。これを使用して、valueを乗算する場合 およびtotal その場合、範囲の開始はvalue*total=1のときです。 範囲の終わりは、value*total=0の場合です。 その他の値は、範囲の途中の日付を示します。

    これが与えるものです:

    SELECT dt,
           CASE SUM( value ) OVER ( ORDER BY dt ASC, value DESC, ROWNUM ) * value
             WHEN 1 THEN 'start'
             WHEN 0 THEN 'end'
           END AS start_end
    FROM   your_table
    UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )
    

    次に、start_endの日付を除外できます。 NULLです これにより、startが交互に表示されるテーブルが残ります。 およびend LAGを使用できる行 日数の差を計算するには:

    SELECT dt - LAG( dt ) OVER ( ORDER BY dt ) + 1 AS days,
           start_end
    FROM   (
      SELECT dt,
             CASE SUM( value ) OVER ( ORDER BY dt ASC, value DESC, ROWNUM ) * value
               WHEN 1 THEN 'start'
               WHEN 0 THEN 'end'
             END AS start_end
      FROM   your_table
      UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )
    )
    WHERE start_end IS NOT NULL
    

    次に行う必要があるのは、SUMすることだけです。 end - startのすべての違い;上記のクエリが表示されます。



    1. plpython3uをインストールできません-postgresql

    2. `having`で`rand()`を使用する

    3. MySQL/PHPで最も人気のある単語を探す

    4. Eclipseを使用してmysqlをjavaに接続します