次のようなテーブルがあります(それを呼び出しましょうaudit
):
+--------------------------------------------------------------------------+
| id | recordId | status | mdate | type | relatedId |
+--------------------------------------------------------------------------+
| 1 | 3006 | A | 2013-04-03 23:59:01.275 | type1 | 1 |
| 2 | 3025 | B | 2013-04-04 00:00:02.134 | type1 | 1 |
| 3 | 4578 | A | 2013-04-04 00:04:30.033 | type2 | 1 |
| 4 | 7940 | C | 2013-04-04 00:04:32.683 | type1 | <NULL> |
| 5 | 3006 | D | 2013-04-04 00:04:32.683 | type1 | <NULL> |
| 6 | 4822 | E | 2013-04-04 00:04:32.683 | type2 | <NULL> |
| 7 | 3006 | A | 2013-04-04 00:06:54.033 | type1 | 2 |
| 8 | 3025 | C | 2013-04-04 00:06:54.033 | type1 | 2 |
...そして何百万行も続きます。そして、別のテーブルを呼び出しますrelated
:
+-------------+
| id | source |
+-------------+
| 1 | src_X |
| 2 | src_Y |
| 3 | src_Z |
| 4 | src_X |
| 5 | src_X |
...そして何十万行も続きます。
両方のテーブルにこれらよりも多くの列がありますが、問題を説明するために必要なのはこれだけです。列がテーブルrelatedId
に結合されrelated
ます。 recordId
も別のテーブルに結合しaudit
、同じrecordId
.
次の出力を生成するクエリを作成しようとしています。
+-----------------+
| source | count |
+-----------------+
| src_X | 1643 |
| src_Y | 255 |
| NULL | 729 |
+-----------------+
カウントは、audit
指定されたtype
(例: "type1"
) を持ち、一連のステータス (例: "A", "B", "C"
) 内にあるレコードの数です。これらのステータスは、外部結合されrelated
、 によってグループ化されsource
ます。
キャッチはaudit
、特定の日付範囲内のレコードのみを含めたいこととaudit
、related
各recordId
. type
さらに、 andの条件に一致するレコードを無視したいが、日付の範囲よりも古いstatus
同じエントリがあります。recordId
したがって、上記のデータ例から明確にするために、 のタイプtype1
と のステータス値がから"A", "B", "C"
までの日付範囲で必要である2013-04-04
とし2013-04-05
ます。行 2 と 4 がカウントに含まれます。行 3 は、 が正しくないため除外されtype
ます。行 5 はステータスが正しくないため除外されます。ステータスとタイプの両方が正しくないため、行 6 は除外されます。行 1 は日付範囲外であるため除外されます。行 7 も除外されます。これは、ステータスとタイプの基準に一致する別の行 (行 1) がrecordId
日付範囲の開始よりも古いためです。行 8 と行 2 の両方が同じrecordId
で基準に一致するため、行 8 は除外されますが、範囲内の 2 つのレコードのうち最も古いレコードのみがカウントされます。
つまり、特定の recordId のエントリがテーブルに初めて表示され、対象の日付範囲内にある場合のみカウントしたいと考えています。
私たちは次のことを考え出しました:
WITH data (recordId, id) AS (
SELECT a.recordId, MIN(a.id)
FROM audit a
WHERE a.status in ('A','B','C')
AND type = 'type1'
GROUP BY a.recordId
)
SELECT r.source, COUNT(*)
FROM data d
JOIN audit a ON d.id = a.id
LEFT JOIN related r ON a.relatedId = r.id
WHERE a.mdate >= '2013-04-04 00:00:00.000'
and a.mdate < '2013-04-05 00:00:00.000'
GROUP BY r.source
これは MSSQL Server 2008 で実行され、現在は監査テーブル ID が自動生成されるという事実に依存しています。id はレコードが挿入された時点で生成され、mdate は挿入タイムスタンプでもあり、一度挿入されたレコードは決して更新されないので、これで問題ないと思います。このクエリは、限られた一連のテスト データに対して正しい出力を提供しているように見えますが、セカンドオピニオンを期待していました。
- このクエリは大丈夫ですか?
- そのパフォーマンスを改善できますか?