1

私は複雑な (少なくとも、私の知識レベルでは) 文字列を書き込もうとしていますが、非常に苦労しています。

これが問題です。t1 という名前と c1 という名前の 2 つのテーブルがあります。

テーブルは次のように定義されます。

table T1:

e_id, char(8),  
e_date, datetime,  
e_status, varchar(2)

table C1:

e_id, char(8),  
e_date, datetime,  
e_status, varchar(2)

各テーブルには、両方のテーブルで見つかる場合と見つからない場合がある識別子 (各テーブル内で一意である場合とそうでない場合がある) のリストと、関連するステータス (T1 テーブルでは「OK」または「R」、 C1 テーブルの「OK」または「C」)、および e_id の出現ごとに関連付けられた日時 e_date

次のようなクエリを作成しようとしています。

  • e_date過去 24 時間以内のを持つ T1 テーブル内のすべての e_id 値を取得します。
  • 過去 30 日間 (e_date > now - 30 日) 以内に T1 で過去 24 時間 ( e_date が現在の時刻 - 24h よりも大きい)内に発生した e_id のすべての出現を取得します (例: e_id が AAAAAAAA の場合)および BBBBBBBB が t1 で e_date が過去 24 時間以内に見つかった場合、e_id の AAAAAAAA および BBBBBBBB が同じテーブル内に出現するが、e_date が過去 30 日以内のものをすべて取得します) 。
  • 全体で見つかったe_status = 'OK'各固有の数を行の結果に追加しますe_idT1 table
  • 全体で見つかったe_Status = 'OK'各固有の数を行の結果に追加しますe_idC1 table

ここにいくつかのサンプルデータ/結果を書くために最善を尽くします。わかりやすくするために、テーブルのデータ型は無視します。現在の日時が 2012-Nov-08 19:00:00 であるとします。

T1:

  1. e_id: 'A'、e_date: 2012-Nov-08 10:00:00、e_status: 'OK'
  2. e_id: 'A' , e_date: 2012-Nov-08 10:00:00 , e_status: 'R'
  3. e_id: 'A' , e_date: 2012-Oct-15 10:00:00 , e_status: 'R'
  4. e_id: 'B'、e_date: 2012-Oct-15 10 : 00:00、e_status: 'OK'
  5. e_id: 'A' , e_date: 2012-Oct-15 10:00:00 , e_status: 'OK'
  6. e_id: 'A' , e_date: 2012-Oct-15 10:00:00 , e_status: 'R'
  7. e_id: 'A' , e_date: 2012-Oct-15 10:00:00 , e_status: 'R'
  8. e_id: 'A' , e_date: 2010-Jan-01 10:00:00 , e_status: 'R'
  9. e_id: 'A' , e_date: 2010-Jan-01 10:00:00 , e_status: 'R'

C1:

  1. e_id: 'A'、e_date: 2012-Oct-01 10 : 00:00、e_status: 'C
  2. e_id: 'B'、e_date: 2012-Oct-01 10 : 00:00、e_status: 'OK'
  3. e_id: 'A'、e_date: 2012-Oct-01 10 : 00:00、e_status: 'C
  4. e_id: 'B'、e_date: 2012-Oct-01 10 : 00:00、e_status: 'OK'
  5. e_id: 'A' , e_date: 2012-Oct-01 10:00:00 , e_status: 'OK'

クエリを実行すると、次のようになります。

e_id, e_date, e_status, r_count, c_count
1. e_id: 'A' , e_date: 2012-Nov-08 10:00:00 , e_status: 'OK' , r_count: 6 , c_count: 2
2. e_id: 'A'、e_date: 2012-Nov-08 10:00:00、e_status: 'R'、r_count: 6、c_count: 2
3. e_id: 'A'、e_date: 2012-Oct-15 10 : 00:00、e_status: 'R' , r_count: 6 , c_count: 2
4. e_id: 'A' , e_date: 2012-Oct-15 10:00:00 , e_status: 'OK' ,r_count:6 , c_count: 2
5. e_id: 'A' , e_date: 2012-Oct-15 10:00:00 , e_status: 'R' , r_count: 6 , c_count: 2
6. e_id: 'A' , e_date: 2012 -10 月 15日 10:00:00、e_status: 'R'、r_count: 6、c_count: 2

申し訳ありませんが、値が間違っていたため、T1 行 3 から 7 (結果の行 3 4 5 6) の日付を変更する必要がありました。

T1 の行 4 はe_id: B、過去 24 時間に何も検出されなかったため、返されませんでした
T1 行 8 および 9 は、過去 30 日を超えていたため、返されませんでした

4

1 に答える 1

2

TDQD — テスト駆動型クエリ設計を行う時が来ました。

過去 24 時間の T1 の行

SELECT DISTINCT e_id
  FROM T1
 WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)

これは、クエリの他の部分で一般的なサブクエリになります。

過去 30 日間の T1 の行...

...過去 24 時間以内に T1 にエントリがあった場所。

SELECT a.e_id
  FROM t1 AS a
  JOIN (SELECT DISTINCT e_id
          FROM T1
         WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
       ) AS b ON b.e_id = a.e_id
 WHERE a.e_date >= DATE_SUB(NOW(), INTERVAL 30 DAY)

必要に応じて他の列を追加できます。

ステータスが「R」の T1 の行数 ...

...過去 24 時間以内に T1 にエントリがあった場所

SELECT a.e_id, COUNT(*) AS r_count  -- Per question; why not t_count?
  FROM t1 AS a
  JOIN (SELECT DISTINCT e_id
          FROM T1
         WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
       ) AS b ON b.e_id = a.e_id
 WHERE a.e_status = 'R'
 GROUP BY a.e_id

ステータスが「C」の C1 の行数 ...

...過去 24 時間以内に T1 にエントリがあった場所

SELECT a.e_id, COUNT(*) AS c_count
  FROM c1 AS a
  JOIN (SELECT DISTINCT e_id
          FROM T1
         WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
       ) AS b ON b.e_id = a.e_id
 WHERE a.e_status = 'C'
 GROUP BY a.e_id

一連のクエリを組み立てて結果を生成する

SELECT a.e_id, a.e_date, a.e_status, c.r_count, d.c_count
  FROM t1 AS a
  JOIN (SELECT DISTINCT e_id
          FROM T1
         WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
       ) AS b ON b.e_id = a.e_id
  LEFT JOIN -- Because there might be no OK rows in T1
       (SELECT a.e_id, COUNT(*) AS r_count
          FROM t1 AS a
          JOIN (SELECT DISTINCT e_id
                  FROM T1
                 WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
               ) AS b ON b.e_id = a.e_id
         WHERE a.e_status = 'OK'
         GROUP BY a.e_id
       ) AS c ON c.e_id = a.e_id
  LEFT JOIN -- Because there might be no OK rows in C1
       (SELECT a.e_id, COUNT(*) AS c_count
          FROM c1 AS a
          JOIN (SELECT DISTINCT e_id
                  FROM T1
                 WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
               ) AS b ON b.e_id = a.e_id
         WHERE a.e_status = 'OK'
         GROUP BY a.e_id
       ) AS d ON d.e_id = a.e_id
 WHERE a.e_date >= DATE_SUB(NOW(), INTERVAL 30 DAY)

おそらく、24 時間サブサブクエリなしでサブクエリを作成することもできますが、できるだけ早く多くの行を削除することが効果的である可能性があります。


TDQD の背後にある概念の利点の 1 つは、中間結果を確認できることです。基本的に些細な構文の問題がいくつかありましたが (MySQL は私のプライマリ DBMS ではないため)、2 つの COUNT サブクエリの JOIN から LEFT JOIN への変更は、クエリを組み立てる際に見つけやすいものです。 . 最初からすべてを正しく行おうとするのは、無駄ではないにしても難しいことです。しかし、一歩一歩積み上げることで、これまでやってきたことに自信が持てるようになります。コンポーネントのサブクエリをテストせずに、これほど複雑なクエリを最初から作成することはありません。

(マイナーな)更新をありがとう、FatalMojo

于 2012-11-09T02:54:34.157 に答える