根据产品和付款表列出具有财务余额的用户

时间:2013-03-16 16:23:33

标签: mysql sql select join

我有一个用户表:

USER表

╔════╦══════╗
║ ID ║ NAME ║
╠════╬══════╣
║  1 ║ A    ║
║  2 ║ B    ║
║  3 ║ C    ║
╚════╩══════╝

付款表

╔════╦═════════╦════════╗
║ ID ║ USER_ID ║ AMOUNT ║
╠════╬═════════╬════════╣
║  1 ║       1 ║   2000 ║
║  2 ║       1 ║   1000 ║
║  3 ║       1 ║   1000 ║
║  4 ║       2 ║   1000 ║
╚════╩═════════╩════════╝

PRODUCT表

╔════╦═════════╦════════╗
║ ID ║ USER_ID ║ AMOUNT ║
╠════╬═════════╬════════╣
║  1 ║       1 ║   1000 ║
║  2 ║       1 ║   1000 ║
║  3 ║       1 ║   1000 ║
║  4 ║       2 ║    500 ║
║  5 ║       2 ║    500 ║
║  6 ║       3 ║   1000 ║
╚════╩═════════╩════════╝

现在我想得到这样的结果:

╔════╦══════╦═════════════════╗
║ ID ║ NAME ║     BALANCE     ║
╠════╬══════╬═════════════════╣
║  1 ║ A    ║ +1000 (or 1000) ║
║  2 ║ B    ║ 0               ║
║  3 ║ C    ║ -1000           ║
╚════╩══════╩═════════════════╝

2 个答案:

答案 0 :(得分:1)

您不能直接加入表,因为表users上有记录,其他表上有多个匹配,而有些记录没有导致无效结果。我能想到的最好的方法是计算不同表上每个用户的总和,并将结果加到表user上。

SELECT  a.*,
        COALESCE(b.totalPayed,0) - COALESCE(c.total,0) balance
FROM    user a
        LEFT JOIN
        (
            SELECT  user_ID, SUM(amount) totalPayed
            FROM    payment
            GROUP   BY user_ID
        ) b ON a.ID = b.user_ID
        LEFT JOIN 
        (
            SELECT  user_ID, SUM(amount) total
            FROM    product
            GROUP   BY user_ID
        ) c ON a.ID = c.user_ID

输出

╔════╦══════╦═════════╗
║ ID ║ NAME ║ BALANCE ║
╠════╬══════╬═════════╣
║  1 ║ A    ║    1000 ║
║  2 ║ B    ║       0 ║
║  3 ║ C    ║   -1000 ║
╚════╩══════╩═════════╝

要进一步了解联接,请访问以下链接:

答案 1 :(得分:1)

 DROP TABLE  IF EXISTS user;
 CREATE TABLE user
 (user_id INT NOT NULL PRIMARY KEY,name CHAR(1) NOT NULL);

 INSERT INTO user VALUES (1 ,'A'),(2,'B'),(3,'C');

 DROP TABLE IF EXISTS payment;
 CREATE TABLE payment
 (payment_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
 ,user_id INT NOT NULL
 ,amount INT NOT NULL
 );

 INSERT INTO payment VALUES
 (1 ,1 ,2000),
 (2 ,1 ,1000),
 (3 ,1 ,1000),
 (4 ,2 ,1000 );

 DROP TABLE IF EXISTS product;

 CREATE TABLE product
 (product_id INT NOT NULL PRIMARY KEY
 ,user_id INT NOT NULL
 ,amount INT NOT NULL
 );

 INSERT INTO product VALUES
 (1 ,1 ,1000 ),
 (2,1 ,1000 ),
 (3,1 ,1000),
 (4,2 ,500 ),
 (5,2 ,500 ),
 (6,3 ,1000);

 SELECT x.*
      , SUM(y.amount) ttl 
   FROM user x 
   JOIN 
      ( SELECT user_id
             , amount 
          FROM payment 
     UNION ALL 
        SELECT user_id
             , amount*-1 
          FROM product
      ) y 
     ON y.user_id = x.user_id 
  GROUP 
     BY user_id;
 +---------+------+-------+
 | user_id | name | ttl   |
 +---------+------+-------+
 |       1 | A    |  1000 |
 |       2 | B    |     0 |
 |       3 | C    | -1000 |
 +---------+------+-------+