简体   繁体   中英

MySQL query combining sums from multiple tables

I have the following query that is trying to generate a list of all clients, their projects, time spent on each project, total invoiced amount and total number of invoices.

SELECT
    c.name as client,
    p.name as project,
    SUM(t.hours) as hours,
    SUM(ci.amount) as invoice_amount,
    COUNT(ci.id) as number_invoices
FROM
    projects p
    INNER JOIN client_master c ON c.harvest_id = p.client_id
    INNER JOIN timesheet t ON t.project_id = p.id 
    LEFT OUTER JOIN projects_contracts pc ON pc.project_id = p.id
    INNER JOIN contracts_invoices ci ON ci.contract_id = pc.contract_id
GROUP BY
    c.name,
    p.name
ORDER BY
    c.name, 
    p.name,
    t.hours

When I run the query, the "hours" are being calculated correctly but the sums/counts for invoice_amount and number_invoices aren't being joined contextually to the project but to the total number of invoices in the table. If I comment out one of the sum()'s then I get the proper value but not when they're both in.

Expected Results

Client A, Project 1, 1000, $10,000, 2

Client A, Project 2, 5000, $5,000, 1

Client B, Project 1, 100, $3000, 1

Actual Results

Client A, Project 1, 1000, $150,000, 20

Client A, Project 2, 5000, $50,000, 81

Client B, Project 1, 100, $83000, 12

I've tried messing w/ the grouping and join statements but haven't found success. Is there something simple I'm overlooking or do I need a total rewrite?

Since invoices are dependant on contracts, and contracts are optional (the left join), make that join also a left join.

SELECT
    c.name as client,
    p.name as project,
    SUM(t.hours) as hours,
    SUM(ci.amount) as invoice_amount,
    COUNT(ci.id) as number_invoices
FROM
    projects p
    INNER JOIN client_master c 
        ON c.harvest_id = p.client_id
    INNER JOIN timesheet t 
        ON t.project_id = p.id 
    LEFT JOIN projects_contracts pc 
        ON pc.project_id = p.id
    LEFT JOIN contracts_invoices ci 
        ON ci.contract_id = pc.contract_id
GROUP BY
    c.name,
    p.name
ORDER BY
    c.name, 
    p.name,
    t.hours

This may not be the best way, but I bet it works

SELECT
    c.name as client,
    p.name as project,
    t.hours as hours,
    ci.amount as invoice_amount,
    ci.count as number_invoices
FROM
    projects p
    INNER JOIN client_master c 
        ON c.harvest_id = p.client_id
    INNER JOIN (SELECT project_id, SUM(hours) AS hours FROM timesheet GROUP BY project_id) t
        ON t.project_id = p.id 
    LEFT OUTER JOIN projects_contracts pc 
        ON pc.project_id = p.id
    LEFT OUTER JOIN (SELECT contract_id, SUM(amount) AS amount, COUNT(DISTINCT id) AS count FROM contracts_invoices GROUP BY contract_id) ci
        ON ci.contract_id = pc.contract_id
GROUP BY
    c.name,
    p.name
ORDER BY
    c.name, 
    p.name,
    t.hours

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM