1

結合する必要がある 2 つのテーブルがあります...「id」で table1 と table2 を結合したいのですが、テーブル 2 の ID は一意ではありません。テーブル 2 に対して返される値は 1 つだけです。この値は、指定された日付範囲 (たとえば 1 か月) 内の「total_sold」という列の合計を表しますが、同時に複数の日付範囲が必要です...

SELECT ta.id, sum(tb.total_sold) as total_sold_this_week, sum(tc.total_sold) as total_sold_this_month
FROM table_a as ta
LEFT JOIN table_b as tb ON ta.id=tb.id AND tb.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -1 WEEK) AND NOW()
LEFT JOIN table_b as tc ON ta.id=tc.id AND tc.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -1 MONTH) AND NOW()
GROUP BY ta.id

これは機能しますが、行を合計しません-IDごとに1行のみを返します... 1行だけではなく、テーブルbから合計を取得するにはどうすればよいですか??? 質問の形式がより多くの作業を必要とするかどうかを批判してください - 必要に応じて書き直してサンプルデータを提供できます - これははるかに大きな問題の単純化されたバージョンです.

-ありがとう

4

1 に答える 1

6

サブクエリの使用

これを解決する 1 つの方法は、サブクエリを使用することです。 LEFT JOIN右側のテーブルの一致ごとに新しい「結果」を作成するため、2 つの LEFT JOIN を使用すると、必要以上の行が作成されます。必要な値をサブ選択することもできますが、これは遅くなる可能性があります。

SELECT ta.id, 
   (SELECT SUM(total_sold) as total_sold 
    FROM table_b 
    WHERE date_sold BETWEEN ADDDATE(NOW(), INTERVAL -1 WEEK) AND NOW()
    AND id=ta.id) as total_sold_this_week, 
   (SELECT SUM(total_sold) as total_sold 
    FROM table_b 
    WHERE date_sold BETWEEN ADDDATE(NOW(), INTERVAL -1 MONTH) AND NOW() 
    AND id = ta.id) as total_sold_this_month 
FROM table_a ta;

結果:

+----+----------------------+--------------------- --+
| | ID | total_sold_this_week | total_sold_this_month |
+----+----------------------+--------------------- --+
| | 1 | 3 | 7 |
| | 2 | 4 | 4 |
| | 3 | ヌル | ヌル |
+----+----------------------+--------------------- --+
3行セット (0.04秒)

SUM(CASE ...) の使用

このメソッドはサブクエリを使用しません (また、大規模なデータ セットではより高速になる可能性があります)。「最大」の日付範囲を使用して table_a と table_b を一度結合し、次に aにSUM()基づいCASEて「より小さい範囲」を計算します。

SELECT ta.*, 
  SUM(total_sold) as total_sold_last_month, 
  SUM(CASE 
    WHEN date_sold BETWEEN NOW() - INTERVAL 1 WEEK AND NOW() 
    THEN total_sold
    ELSE 0 
    END) as total_sold_last_week 
FROM table_a AS ta 
LEFT JOIN table_b AS tb 
   ON ta.id=tb.id AND tb.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -1 MONTH) AND NOW() 
GROUP BY ta.id;

これは、サブクエリの例とほぼ同じ結果セットを返します。

+----+-----------------------+-------------------- --+
| | ID | total_sold_last_month | total_sold_last_week |
+----+-----------------------+-------------------- --+
| | 1 | 7 | 3 |
| | 2 | 4 | 4 |
| | 3 | ヌル | 0 |
+----+-----------------------+-------------------- --+
3 行セット (0.00 秒)

唯一の違いは、0代わりにNULL. この方法を使用して必要な数の日付範囲を要約できますが、返される行をON句の最大範囲に制限するのがおそらく最善です。

それがどのように機能するかを示すために: GROUP BYand呼び出しを削除し、SELECT にSUM()追加すると、次のように返されます。date_sold

+----+------------+--------------------------------------+------- ---------------+
| | ID | 販売日 | total_sold_last_month | total_sold_last_week |
+----+------------+--------------------------------------+------- ---------------+
| | 1 | 2010-04-30 | 2 | 2 |
| | 1 | 2010-04-24 | 2 | 0 |
| | 1 | 2010-04-24 | 2 | 0 |
| | 1 | 2010-05-03 | 1 | 1 |
| | 2 | 2010-05-03 | 4 | 4 |
| | 3 | ヌル | ヌル | 0 |
+----+------------+--------------------------------------+------- ---------------+
6行セット (0.00秒)

GROUP BY idと2 つのtotal_soldSUM()列を使用すると、結果が得られます。

古いアドバイス

2 つの異なる日付範囲を混在させる前に、GROUP BYtable1 のテーブル ID を使用してグループ化し、SUM()集計関数を使用して返された行を合計することができました。

SELECT ta.id, SUM(tb.total_sold) as total_sold_this_week
FROM table_a as ta
LEFT JOIN table_b as tb 
ON ta.id=tb.id AND tb.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -3 WEEK) AND NOW()
GROUP BY ta.id
+----+----------------------+
| | ID | total_sold_this_week |
+----+----------------------+
| | 1 | 7 |
| | 2 | 4 |
| | 3 | ヌル |
+----+----------------------+
3 行セット (0.00 秒)

テストデータ

NOW()は 2010 年 5 月 3 日です

mysql> select * from table_a; select * from table_b;
+----+
| | ID |
+----+
| | 1 |
| | 2 |
| | 3 |
+----+
3 行セット (0.00 秒)

+----+------------+------------+
| | ID | 販売日 | 総販売 |
+----+------------+------------+
| | 1 | 2010-04-24 | 2 |
| | 1 | 2010-04-24 | 2 |
| | 1 | 2010-04-30 | 2 |
| | 1 | 2010-05-03 | 1 |
| | 2 | 2010-05-03 | 4 |
+----+------------+------------+
5 行セット (0.00 秒)
于 2010-05-03T15:53:02.537 に答える