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

OracleSQL-2つの日付から月までのユーザーを選択します

    このクエリは、月末現在の有効なアクティブユーザー数を示しています。

    仕組み:

    1. 各入力行を変換します(StartDateを使用) およびEndDate 値)を2つに アクティブユーザー数が増加した時点を表す行(StartDate) )およびデクリメント(EndDate )。 NULLを変換する必要があります NULLであるため、遠い日付の値になります 値は、NULL以外の後ではなく前にソートされます 値:

      これにより、データは次のようになります。

      OnThisDate   Change
      2018-01-01        1
      2019-01-01       -1
      2018-01-01        1
      9999-12-31       -1
      2019-01-01        1
      2019-06-01       -1
      2017-01-01        1
      2019-03-01       -1
      
    2. 次に、単にSUM OVER Change その特定の日付の時点でのアクティブユーザー数を取得するための値(並べ替え後):

      したがって、最初にOnThisDateで並べ替えます :

      OnThisDate   Change
      2017-01-01        1
      2018-01-01        1
      2018-01-01        1
      2019-01-01        1
      2019-01-01       -1
      2019-03-01       -1
      2019-06-01       -1
      9999-12-31       -1
      

      次に、SUM OVER

      OnThisDate   ActiveCount
      2017-01-01             1
      2018-01-01             2
      2018-01-01             3
      2019-01-01             4
      2019-01-01             3
      2019-03-01             2
      2019-06-01             1
      9999-12-31             0
      
    3. 次に、PARTITION (グループ化ではありません!)行を月ごとに並べ替え、日付で並べ替えて、最後のActiveCountを識別できるようにします。 その月の行(これは実際にはWHEREで発生します ROW_NUMBER()を使用した最も外側のクエリの およびCOUNT() 毎月PARTITION ):

      OnThisDate   ActiveCount    IsLastInMonth
      2017-01-01             1                1
      2018-01-01             2                0
      2018-01-01             3                1
      2019-01-01             4                0
      2019-01-01             3                1
      2019-03-01             2                1
      2019-06-01             1                1
      9999-12-31             0                1
      
    4. 次に、IsLastInMonth = 1でフィルタリングします。 (実際には、ROW_COUNT() = COUNT(*)PARTITION内 )最終的な出力データを提供するには:

      At-end-of-month     Active-count
      2017-01                        1
      2018-01                        3
      2019-01                        3
      2019-03                        2
      2019-06                        1
      9999-12                        0
      

    At-end-of-monthが原因で、結果セットに「ギャップ」が生じます。 列には、Active-countがある行のみが表示されます 値は、考えられるすべての暦月を含めるのではなく、実際に変更されましたが、冗長なデータが除外されるため、(私に関する限り)理想的です。ギャップを埋めるには、次のAt-end-of-monthに到達するまで、追加の月ごとに出力行を繰り返すだけで、アプリケーションコード内で行うことができます。 値。

    これは、SQL ServerでT-SQLを使用したクエリです(現在、Oracleにアクセスできません)。そして、これが私が解決策にたどり着いたSQLFiddleです: http://sqlfiddle.com/# !18 / ad68b7 / 24

    SELECT
      OtdYear,
      OtdMonth,
      ActiveCount
    FROM
      (
    
        -- This query adds columns to indicate which row is the last-row-in-month ( where RowInMonth == RowsInMonth )
        SELECT
          OnThisDate,
          OtdYear,
          OtdMonth,
          ROW_NUMBER() OVER ( PARTITION BY OtdYear, OtdMonth ORDER BY OnThisDate ) AS RowInMonth,
          COUNT(*) OVER ( PARTITION BY OtdYear, OtdMonth ) AS RowsInMonth,
          ActiveCount
        FROM
          (
            SELECT
              OnThisDate,
              YEAR( OnThisDate ) AS OtdYear,
              MONTH( OnThisDate ) AS OtdMonth,
              SUM( [Change] ) OVER ( ORDER BY OnThisDate ASC ) AS ActiveCount
            FROM
              (
                SELECT
                  StartDate AS [OnThisDate],
                  1 AS [Change]
                FROM
                  tbl
    
                UNION ALL
    
                SELECT
                  ISNULL( EndDate, DATEFROMPARTS( 9999, 12, 31 ) ) AS [OnThisDate],
                  -1 AS [Change]
                FROM
                  tbl
              ) AS sq1
          ) AS sq2
      ) AS sq3
    WHERE
      RowInMonth = RowsInMonth
    ORDER BY
      OtdYear,
      OtdMonth
    

    このクエリはできます エイリアス(OtdYearなど)を使用する代わりに、集計関数とウィンドウ関数を直接使用することで、ネストされたクエリの数を減らします。 、ActiveCount など)が、クエリを理解するのがはるかに難しくなります。



    1. MySQL接続タイムアウト設定を確認/変更するにはどうすればよいですか?

    2. SparkからPostgresへの分析データの挿入

    3. Oracle結合からAnsi結合への変換

    4. 平均加重価格を見つけるためのクエリ