【问题标题】:multiple tables (one is a subquery) join多个表(一个是子查询)连接
【发布时间】:2012-01-27 04:58:52
【问题描述】:

我有(再次)这个表:

User:
id | name
-------------
1  | 'John'
2  | 'Peter'
3  | 'Luke'

Accounts:
id | userid | amount | date
--------------------------
1  | 1      | 1000   | '2012-01-26'
2  | 1      | 2000   | '2011-12-25'
3  | 1      | 1000   | '2012-01-25'
4  | 2      | 1500   | '2012-01-15'
5  | 3      | 2500   | '2011-11-30'

我需要收集数据,所以我同时有一个包含用户的结果集,每个用户的帐户数,每个用户的帐户金额总和,以及每个用户的帐户,但仅限于当前年份的日期...

类似这样的:

Some-query:
UserName | CountAccts | SumAccts | CountAcctsThisYear
-----------------------------------------------------
'John'   | 3          | 4000     | 2
'Peter'  | 1          | 1500     | 1
'Luke'   | 1          | 2500     | 0

我设法通过此查询获得前 3 列:

SELECT u.name as Username,
       COUNT(a.id) as CountAccts,
       SUM(a.amount) as SumAccts
FROM   User u
LEFT JOIN Accounts a ON u.id = a.userid
GROUP BY u.id;

另外,我可以用另一个得到第一列和最后一列:

SELECT u.name as Username,
       COUNT(acctsthisyear.id) as CountAcctsThisYear
FROM   User u
LEFT JOIN (SELECT a.id
             FROM Accounts a
            WHERE DATE_FORMAT(a.date,'%Y') = DATE_FORMAT(CURDATE(),'%Y')
          ) AS acctsthisyear ON u.id = acctsthisyear.userid
GROUP BY u.id;

但是,问题来了,我无法设法以这样的方式使用这两个查询来获得我期望的最终结果......

我有... - 尝试将 Accounts 表和 acctsthisyear 子查询与 User 表左连接(按 us.id 字段分组),但我得到的只是这样的:

UserName | CountAccts | SumAccts | CountAcctsThisYear
-----------------------------------------------------
'John'   | 6          | 6000     | 6
'Peter'  | 1          | 1500     | 1
'Luke'   | 0          | 0        | 0

(不记得所有细节,但问题是,例如,CountAcctsThisyear 中 'John' 的 2 个结果在结果中也出现了重复,并且所有的都被相乘了......)

  • 尝试将每个查询作为子查询: 选择 * 从 (也选择了 u.id 作为 ufid 的第一个查询)AS 优先, (也选择了以 u.id 作为 usid 的第二个查询)作为第二个 按 ufid、usid 分组

得到了这样的东西:

UserName | CountAccts | SumAccts | CountAcctsThisYear
-----------------------------------------------------
'John'   | 3          | 4000     | 2
'Peter'  | 1          | 1500     | 2
'Luke'   | 1          | 2500     | 2
'John'   | 3          | 4000     | 1
'Peter'  | 1          | 1500     | 1
'Luke'   | 1          | 2500     | 1
'John'   | 3          | 4000     | 0
'Peter'  | 1          | 1500     | 0
'Luke'   | 1          | 2500     | 0

(如果我反转 Group by 元素,我得到的都是相同的,但按不同的顺序分组......)

任何方式......就是这样......关于什么是实现我正在寻找的正确方法的任何想法?我对此感到非常沮丧,因为我真的不是 SQL 专家,尤其是联接方面的专家:-/

【问题讨论】:

    标签: mysql sql select join one-to-many


    【解决方案1】:

    试试这个:

    SELECT u.`Name` as UserName,
           Count(*) as CountAccts,
           SUM(a.`amount`) as SumAccts,
           COALESCE(iTable.CountAcctsThisYear, 0) as CountAcctsThisYear
    FROM    `User` u INNER JOIN `Accounts` a
                        ON u.`ID` = a`.`ID`
                   LEFT JOIN
                       (SELECT `ID`, Count(*) as CountAcctsThisYear
                        FROM `Accounts`
                        WHERE DATE_FORMAT(`date`,'%Y') = DATE_FORMAT(CURDATE(),'%Y')
                        GROUP BY `ID`) as iTable
                    ON `User`.`ID` = iTable.`ID`
    GROUP BY `User`.`Name`
    

    【讨论】:

    • 谢谢!我还在测试,因为我的真实数据有很多条件,但最重要的是我发布的东西......现在,这似乎是正确的答案,我会在测试完成后告诉你!
    【解决方案2】:
    SELECT u.name as Username,
           COUNT(a.id) as CountAccts,
           SUM(a.amount) as SumAccts,
           SUM( CASE WHEN YEAR(a.date) = YEAR(CURDATE()) THEN 1 ELSE 0 END ) 
               as CountAcctsThisYear
    FROM   User u
    LEFT JOIN Accounts a ON u.id = a.userid
    GROUP BY u.id;
    

    【讨论】:

    • :Group By 应该是 a.userid
    • 如何在表中按 u.id 分组,其中 u.id 不会是倍数。它是独一无二的。我认为 group by 应该是 a.userid。你测试过吗?
    • a.userid 和 u.id 一样,我们在这个条件下加入。
    【解决方案3】:
    SELECT u.name as Username,
           COUNT(a.userid) as CountAccts,
           SUM(a.amount) as SumAccts,
           SUM( CASE WHEN YEAR(a.date) = YEAR(CURDATE()) THEN 1 ELSE 0 END ) 
               as CountAcctsThisYear
    FROM Accounts a 
    INNER JOIN  User u ON u.id = a.userid
    GROUP BY a.userid;
    

    【讨论】:

    • @Benjam:我认为主表应该是 Accounts 并且应该采用 Inner join。所以用户必须出现在用户表中。它将避免重复。并会得到适当的结果。
    • 对于没有帐户的用户失败。 OP 将 LEFT JOIN 用于 3 列解决方案是有原因的,这对他来说效果很好。
    • 我正在考虑用户在帐户表中至少有一个帐户(行)。所以会得到用户拥有帐户的结果。如果这不是必需的,则应采用左连接并且表顺序将发生变化。
    【解决方案4】:
    SELECT u.name as Username,
           COUNT(a.id) as CountAccts,
           SUM(a.amount) as SumAccts
    FROM   User u
    INNER JOIN Accounts a ON u.id = a.userid
    GROUP BY u.id,YEAR(a.date)
    

    试试这个!!!

    【讨论】:

      猜你喜欢
      • 2021-08-25
      • 1970-01-01
      • 2017-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 2018-07-06
      • 2018-12-10
      相关资源
      最近更新 更多