在INNER JOIN SQL查询上使用GROUP BY和ORDER BY

Nic*_*ick 5 sql inner-join

我使用以下查询从三个表中分组客户的工作时间和费用,一个用于客户,一个用于工作时间,一个用于费用:

SELECT  a.*,
        COALESCE(b.totalCount, 0) AS CountWork,
        COALESCE(b.totalAmount, 0) AS WorkTotal,
        COALESCE(c.totalCount, 0) AS CountExpense,
        COALESCE(c.totalAmount, 0) AS ExpenseTotal
FROM    clients A
        LEFT JOIN
        (
            SELECT  Client, 
                    COUNT(*) totalCount,
                    SUM(Amount) totalAmount
            FROM    work_times
            WHERE   DATE BETWEEN '2013-01-01' AND '2013-02-01'
            GROUP   BY Client
        ) b ON a.Client = b.Client
        LEFT JOIN
        (
            SELECT  Client, 
                    COUNT(*) totalCount,
                    SUM(Amount) totalAmount
            FROM    expenses
            WHERE   DATE BETWEEN '2013-01-01' AND '2013-02-01'
            GROUP   BY Client
        ) c ON a.Client = c.Client
WHERE   b.Client IS NOT NULL OR
        c.Client IS NOT NULL
Run Code Online (Sandbox Code Playgroud)

你可以在这里看到查询工作.

我正在尝试修改此查询,以便每个客户端按月排序,然后按客户端排序.我试图用以下修改的查询来做到这一点:

SELECT  a.*,
        COALESCE(b.totalCount, 0) AS CountWork,
        COALESCE(b.totalAmount, 0) AS WorkTotal,
        COALESCE(c.totalCount, 0) AS CountExpense,
        COALESCE(c.totalAmount, 0) AS ExpenseTotal
FROM    clients A
        LEFT JOIN
        (
            SELECT  Client, 
                    COUNT(*) totalCount,
                    SUM(Amount) totalAmount,
                    SUBSTR(Date, 1, 7) as Month
            FROM    work_times
            GROUP   BY Month,Client
            ORDER BY Month
        ) b ON a.Client = b.Client
        LEFT JOIN
        (
            SELECT  Client, 
                    COUNT(*) totalCount,
                    SUM(Amount) totalAmount,
                    SUBSTR(Date, 1, 7) as Month
            FROM    expenses
            GROUP   BY Month,Client
            ORDER BY Month,Client
        ) c ON a.Client = c.Client
WHERE   b.Client IS NOT NULL OR
        c.Client IS NOT NULL
Run Code Online (Sandbox Code Playgroud)

您可以在此处查看修改后的查询.

虽然这不是很正常.即使2013年1月有工作时间且2013年2月有费用(因此应该有2行),客户端B也只返回一行,并且看起来行是由客户订购而不是月订购的.有人可以建议如何修改查询以获得所需的输出,对于第二小提琴的例子将是:

????????????????????????????????????????????????????????????????
? CLIENT ? COUNTWORK ? WORKTOTAL ? COUNTEXPENSE ? EXPENSETOTAL ?
????????????????????????????????????????????????????????????????
? A      ?         1 ?        10 ?            1 ?           10 ?
? B      ?         1 ?        20 ?            0 ?            0 ?
? A      ?         1 ?        15 ?            0 ?            0 ?
? B      ?         0 ?        0  ?            1 ?           10 ?
? C      ?         1 ?        10 ?            0 ?            0 ?
????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

Tar*_*ryn 2

除非我在需求中遗漏了某些内容,否则您需要做的就是获取客户和日期的列表,然后将其加入到您的子查询中。所以你的查询将是:

SELECT a.*,
  COALESCE(b.totalCount, 0) AS CountWork,
  COALESCE(b.totalAmount, 0) AS WorkTotal,
  COALESCE(c.totalCount, 0) AS CountExpense,
  COALESCE(c.totalAmount, 0) AS ExpenseTotal
FROM 
(
  select distinct c.Client, d.Month
  from clients c
  cross join
  (
    select SUBSTR(Date, 1, 7) as Month
    from work_times
    union 
    select SUBSTR(Date, 1, 7) as Month
    from expenses
  ) d
) A
LEFT JOIN
(
  SELECT  Client, 
    COUNT(*) totalCount,
    SUM(Amount) totalAmount,
    SUBSTR(Date, 1, 7) as Month
  FROM    work_times
  GROUP   BY Month,Client
  ORDER BY Month,Client
) b 
  ON a.Client = b.Client
  and a.month = b.month
LEFT JOIN
(
  SELECT  Client, 
    COUNT(*) totalCount,
    SUM(Amount) totalAmount,
    SUBSTR(Date, 1, 7) as Month
  FROM    expenses
  GROUP   BY Month,Client
  ORDER BY Month,Client
) c 
  ON a.Client = c.Client
  and a.month = c.month
WHERE   b.Client IS NOT NULL OR
        c.Client IS NOT NULL
order by a.month, a.client
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle 演示

结果是:

| CLIENT |   MONTH | COUNTWORK | WORKTOTAL | COUNTEXPENSE | EXPENSETOTAL |
--------------------------------------------------------------------------
|      A | 2013-01 |         1 |        10 |            1 |           10 |
|      B | 2013-01 |         1 |        20 |            0 |            0 |
|      A | 2013-02 |         1 |        15 |            0 |            0 |
|      B | 2013-02 |         0 |         0 |            1 |           20 |
|      C | 2013-02 |         1 |        10 |            0 |            0 |
Run Code Online (Sandbox Code Playgroud)