web-dev-qa-db-fra.com

Comparez la somme de deux résultats sélectionnés

Utiliser Firebird, j'ai deux tables, Orders et DespatchedParts.

Orders Table:

ID  CustomerID  Total_number_parts
--  ----------  ------------------
1   1           5
2   1           4
3   2           10
4   1           5
5   3           20

DespatchedParts Table:

ID  OrdersID  PartQty
--  --------  -------
1   1         2
2   1         3
3   2         10
4   3         10
5   3         10

Donc, dans la table Orders la somme de Total_number_parts pour les commandes de 1 + 4 + 5 = 14.

Puis cherche dans DespatchedParts, nous voulons la somme de PartQty pour le client 1, donc 2 + 3 = 5.

Donc, le client 1 a commandé 14 parties et 5 ont été expédiés. Je veux obtenir tous les identifiants du client qui ont reçu toutes leurs parties.

Vous trouverez ci-dessous ce que j'ai jusqu'à présent. Je ne sais pas où mettre la partie sum(total_number_parts) = sum(qtyparts).

Select a.customerID, sum(a.Total_number_parts)
From Orders a
Join (Select sum(PartQty) from OrderParts Group by customerID) B
   on B.customerID = a.customerID
Group By a.CustomerID
2
Simon

Vous souhaitez sélectionner tous les clients dont les commandes ont été complètement remplies. Ainsi, vous devez d'abord savoir combien de pièces commandées au total au total:

select customerid, sum(total_number_parts) ordered
from orders
group by customerid

Vous devez également savoir combien de pièces ont été expédiées pour chaque client. Vous devrez rejoindre des commandes et des pièces expédiées pour obtenir le CustomerID associé aux pièces expédiées.

select o.customerid, sum(dp.partqty) dispatched
from orders o 
left join dispatched_parts dp
   on dp.ordersid = o.id 
group by o.customerid

J'utilise une jointure gauche ici, vous obtenez donc également la quantité totale si aucune pièce n'a été envoyée. Cela n'est pas nécessaire pour votre question, mais devient pertinente si vous souhaitez obtenir tous les clients qui n'ont pas encore reçu leurs pièces.

Nous combinons ces deux et appliquons la condition demandée dans la clause où:

select a.customerid
from (
    select customerid, sum(total_number_parts) ordered
    from orders
    group by customerid
) a
inner join (
    select o.customerid, sum(dp.partqty) dispatched
    from orders o 
    left join dispatched_parts dp
       on dp.ordersid = o.id 
    group by o.customerid
) b on b.customerid = a.customerid
where ordered = dispatched

En supposant les ordonnations corrigées (1, 1, 3, 5, 5), j'ai suggéré dans les commentaires, ces rendements

customerid
2
3

Sinon, vous pouvez déplacer entièrement la deuxième partie dans la clause WHERE en le faisant une sous-requête corrélée:

select a.customerid
from (
    select customerid, sum(total_number_parts) ordered
    from orders
    group by customerid
) a
where a.ordered = (
    select sum(dp.partqty) 
    from orders o 
    left join dispatched_parts dp
       on dp.ordersid = o.id 
    where o.customerid = a.customerid
)
2
Mark Rotteveel

Configurer les données de test:

CREATE TABLE #order (id INT, customerid INT, total_number_parts INT)
INSERT INTO #order ( id ,customerid ,total_number_parts)VALUES  ( 1,1,5)
INSERT INTO #order ( id ,customerid ,total_number_parts)VALUES  ( 2,1,4)
INSERT INTO #order ( id ,customerid ,total_number_parts)VALUES  ( 3,2,10)
INSERT INTO #order ( id ,customerid ,total_number_parts)VALUES  ( 4,1,50)
INSERT INTO #order ( id ,customerid ,total_number_parts)VALUES  ( 5,3,20)

CREATE TABLE #despatchedparts (id INT, ordersid INT, partqty int)
INSERT INTO #despatchedparts (id, ordersid, partqty) VALUES (1,1,2)
INSERT INTO #despatchedparts (id, ordersid, partqty) VALUES (2,1,3)
INSERT INTO #despatchedparts (id, ordersid, partqty) VALUES (3,2,10)
INSERT INTO #despatchedparts (id, ordersid, partqty) VALUES (4,3,10)
INSERT INTO #despatchedparts (id, ordersid, partqty) VALUES (5,3,10)

Solution:

SELECT o.id AS [OrderId], o.customerid AS [CustomerId], o.total_number_parts AS [Parts orded], SUM(d.partqty) AS [Parts sent],
    CASE WHEN o.total_number_parts = SUM(d.partqty) THEN 'All delivered'
    WHEN SUM(d.partqty) = 0 THEN 'None delivered'
    ELSE 'Part delivered' END AS [Status]
FROM #order o
LEFT outer JOIN #despatchedparts d ON o.id = d.ordersid
GROUP BY o.id, o.customerid, o.total_number_parts

Je remarquai seulement que c'était pour Firebird à partir de tout ce qui est désolé si cela ne fonctionne pas. Vous pouvez aussi faire:

SELECT o.*
FROM #order o
WHERE o.total_number_parts = (SELECT SUM(partqty) FROM #despatchedparts d WHERE o.id = d.ordersid)
0
Paul