INNER JOIN查询使用三个表来返回符合条件的行的Count和Sum

Nic*_*ick 4 sql inner-join multiple-tables

我正在尝试从三个SQL表中加入数据.

表格格式如下:

客户

??????????
? CLIENT ?
??????????
? A      ?
? B      ?
? C      ?
? D      ?
??????????
Run Code Online (Sandbox Code Playgroud)

work_times

???????????????????????????????????????????
? Client ?   Work   ? Amount ?    Date    ?
???????????????????????????????????????????
? A      ? Web Work ?     10 ? 2013-01-12 ?
? B      ? Research ?     20 ? 2013-01-20 ?
? A      ? Web Work ?     15 ? 2013-01-21 ?
? C      ? Research ?     10 ? 2013-01-28 ?
???????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

花费

???????????????????????????????????????????
? Client ?   Item   ? Amount ?    Date    ?
???????????????????????????????????????????
? A      ? Software ?     10 ? 2013-01-12 ?
? B      ? Software ?     20 ? 2013-01-20 ?
???????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

我想要一个查询,返回每个客户的工作和费用的计数和总和,即:

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

到目前为止,我有以下内容:

SELECT clients.Client,
 COUNT(distinct work_times.id) AS num_work,
 COUNT(expenses.id) AS num_expenses
FROM
 clients
 INNER JOIN work_times ON work_times.Client = clients.Client
   INNER JOIN expenses ON expenses.Client = work_times.Client
GROUP BY
  clients.Client
Run Code Online (Sandbox Code Playgroud)

这似乎沿着正确的路线,但它跳过没有费用的客户端,似乎将num_expenses乘以num_work.我还想添加一个WHERE子句来指定只返回两个日期之间的工作时间和费用.我需要对查询进行哪些更改才能获得所需的输出?

Joh*_*Woo 6

您需要单独计算子查询中的值.WHERE最外层查询的子句的目的是过滤掉至少在一个表上记录的记录.所以在这种情况下,Client D不会显示在结果列表中.

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)

UPDATE

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