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

SQL Server CTE を使用して、交差する日付をマージできますか?

    完全な書き直し:

    ;WITH new_grp AS (
       SELECT r1.UserId, r1.StartTime
       FROM   @requests r1
       WHERE  NOT EXISTS (
              SELECT *
              FROM   @requests r2
              WHERE  r1.UserId = r2.UserId
              AND    r2.StartTime <  r1.StartTime
              AND    r2.EndTime   >= r1.StartTime)
       GROUP  BY r1.UserId, r1.StartTime -- there can be > 1
       ),r AS (
       SELECT r.RequestId, r.UserId, r.StartTime, r.EndTime
             ,count(*) AS grp -- guaranteed to be 1+
       FROM   @requests r
       JOIN   new_grp n ON n.UserId = r.UserId AND n.StartTime <= r.StartTime
       GROUP  BY r.RequestId, r.UserId, r.StartTime, r.EndTime
       )
    SELECT min(RequestId) AS RequestId
          ,UserId
          ,min(StartTime) AS StartTime
          ,max(EndTime)   AS EndTime
    FROM   r
    GROUP  BY UserId, grp
    ORDER  BY UserId, grp
      

    要求された結果を生成し、実際に 分離サブグループと重複を含む、考えられるすべてのケースをカバーしています。 data.SE での動作デモ .

      <リ>

      CTE 1
      重複する間隔の新しいグループが始まる (一意の!) 時点を見つけます。

      <リ>

      CTE 2
      新しいグループの開始を個々の間隔ごとに (それを含めて) カウントし、ユーザーごとに一意のグループ番号を形成します。

      <リ>

      最終選択
      グループをマージし、グループの開始を早め、終了を遅らせます。

    T-SQL ウィンドウ関数 max() のため、いくつかの困難に直面しました または sum() ORDER BY を受け入れない ウィンドウ内の句。パーティションごとに 1 つの値しか計算できないため、パーティションごとに現在の合計/カウントを計算することはできません。 PostgreSQL または Oracle で動作します (もちろん、MySQL では動作しません。ウィンドウ関数も CTE もありません)。

    最終的なソリューションでは、CTE を 1 つ余分に使用しますが、同じくらい高速になるはずです。



    1. SQL 既存の列に外部キーを追加

    2. Laravel-テーブルを動的に作成する(移行なし)

    3. 一重引用符を回避する衛生状態は、SQL ServerのSQLインジェクションによってどのように打ち負かされますか?

    4. Ubuntu20.04へのMySQLのインストールと構成