2

ユーザーとその支払いを説明する 2 つのテーブルがあります。

CREATE TABLE test_users
(id int IDENTITY NOT NULL,
name varchar(25),
PRIMARY KEY (id));

CREATE TABLE test_payments
(id int IDENTITY NOT NULL,
user_id int NOT NULL,
money money NOT NULL,
date datetime NOT NULL,
PRIMARY KEY (id));

INSERT INTO test_users (name) 
VALUES ('john');

INSERT INTO test_users (name) 
VALUES ('peter');

INSERT INTO test_payments (user_id, money, date)
VALUES (1, $1, CONVERT(datetime, '15.12.2012'));

INSERT INTO test_payments (user_id, money, date)
VALUES (1, $2, CONVERT(datetime, '16.12.2012'));

INSERT INTO test_payments (user_id, money, date)
VALUES (2, $1, CONVERT(datetime, '16.12.2012'));

INSERT INTO test_payments (user_id, money, date)
VALUES (2, $3, CONVERT(datetime, '17.12.2012'));

INSERT INTO test_payments (user_id, money, date)
VALUES (1, $1, CONVERT(datetime, '19.12.2012'));

テーブル test_users:

id  name
-------------
1   john
2   peter

テーブル test_payments:

id  user_id money   last_activity
---------------------------------------
1   1   1.0000  2012-12-15
2   1   2.0000  2012-12-16
3   2   1.0000  2012-12-16
4   2   3.0000  2012-12-17
5   1   1.0000  2012-12-19

私は私を示すユーザー統計を作成する必要があります:

  1. ユーザー名
  2. 一定期間の合計料金
  3. ユーザーの最後のアクティビティの日付 (一定期間ではなく一般的なもの)。

たとえば、期間 15-18.12.12 を使用すると、次の結果が期待されます。

name    total    last_activity
--------------------------------
peter   $4       2012-12-17
john    $3       2012-12-19

次のクエリを試しました。

SELECT u.*, SUM(p.money) total, MAX(p.date) last_activity
FROM test_users u
JOIN test_payments p
ON u.id= p.user_id
WHERE p.date BETWEEN CONVERT(datetime, '15.12.2012') AND CONVERT(datetime, '18.12.2012')
GROUP BY u.id, u.name
ORDER BY total DESC;

しかし、last_activity も日付範囲内にあるため、間違った結果が得られます。

id  name    total   last_activity
--------------------------------
2   peter   4.0000  2012-12-17
1   john    3.0000  2012-12-16

解決策を提案してください。

4

4 に答える 4

3

where条件を句からcaseステートメントに移動する必要があります。

SELECT u.id, u.name,
      SUM(case when p.date BETWEEN CONVERT(datetime, '15.12.2012') AND CONVERT(datetime, '18.12.2012')
               then p.money
          end) total,
      MAX(p.date) last_activity
FROM test_users u JOIN
     test_payments p
     ON u.id= p.user_id
GROUP BY u.id, u.name
ORDER BY total DESC;

その期間に支払いを行ったユーザーのみが必要な場合は、次を含めることができます。

having total is not null

NULL 値を NULL ではなく 0 として表示するelse 0場合は、case ステートメントに含めます。

于 2012-12-20T16:52:28.080 に答える
3

私が自分で作業している間に、他のいくつかの回答がポップアップしたように見えますが、とにかくここにあります。ここに動作するSQLフィドルがあります:http://sqlfiddle.com/#!3/14808/6

基本的に、日付範囲に関係なく最大日付を取得するにはクエリが必要です。これを相関サブクエリとして実行することにしました。

SELECT 
  u.id,
  u.name,
  SUM(IsNull(money,0)) as TotalMoneyInRange,
  (SELECT max(date) FROM test_payments where user_id = u.id) AS LastPaymentOverAll
FROM test_users AS u
LEFT JOIN test_payments AS p
ON u.id = p.user_id
WHERE 
  p.date IS NULL OR
  p.date between 
  CAST('12-11-2012' AS datetime) --range begin
  and 
  CAST('12-16-2012' as datetime) --range end
GROUP BY u.id, u.name
于 2012-12-20T17:07:11.647 に答える
1

サブクエリを使用して結果を取得することもできます。

SELECT u.*, total, last_activity
FROM test_users u
JOIN
(
  select sum(money) total, user_id
  from test_payments
  WHERE date BETWEEN CONVERT(datetime, '2012-12-15') 
    AND CONVERT(datetime, '2012-12-18')
  group by user_id
) p
  ON u.id= p.user_id
inner join 
(
  select user_id, max(date) last_activity
  from test_payments
  group by user_id
) p1
  on p.user_id = p1.user_id
ORDER BY total DESC;

デモで SQL Fiddle を参照してください

于 2012-12-20T17:02:19.423 に答える
0

次のように、WHERE 句を持たない MAX 日付のサブクエリを追加できます。

SELECT 
  u.*
  ,SUM(p.money) total
  ,a.max_date last_activity
FROM test_users u
  INNER JOIN test_payments p ON u.id = p.user_id
  INNER JOIN (SELECT user_id, MAX(date) AS max_date 
              FROM test_payments 
              GROUP BY user_id) a ON u.id = a.user_id
WHERE p.date BETWEEN CONVERT(datetime, '15.12.2012') AND CONVERT(datetime, '18.12.2012')
GROUP BY u.id, u.name, a.max_date
ORDER BY total DESC;
于 2012-12-20T17:05:46.357 に答える