Probleme mit SQL und Aggregaten

7

Mit dieser Abfrage:

SELECT SUM(qty) AS sumQty,
       cnetprodid
FROM   quoteitem
WHERE  ordered = 1
       AND sageSOPOrderReturnLineID IS NOT NULL
       AND LEN(LTRIM(RTRIM(cnetprodid))) > 0
       AND cnetprodid LIKE 'S%'
       AND price > 10
       AND created > DATEADD(MONTH, -3, GETDATE())
GROUP  BY cnetprodid
ORDER  BY SUM(qty) DESC 

Ich bekomme eine Reihe pro Produkt zurück, die oberste Reihe hat 294 als sumQtyund 'S10381902' alscnetprodid

Geben Sie diese Abfrage ein:

SELECT SUM(qty) AS sumQty,
       p.ProdID,
       p.CatID
FROM   quoteitem
       INNER JOIN cds_prod AS p
         ON p.ProdID COLLATE Latin1_General_CI_AS = cnetprodid
       INNER JOIN cds_atr AS a
         ON a.ProdID COLLATE Latin1_General_CI_AS = p.ProdID
       INNER JOIN lan_cat_sections AS c
         ON c.attID = a.atrID
             OR ( LEN(ISNULL(c.attID, '')) = 0
                  AND c.cat_id LIKE p.CatID + '%' )
                AND ( ( c.[include] = 0
                        AND a.valID NOT IN (SELECT Value
                                            FROM   Split(c.valID, ',')) )
                       OR ( c.[include] = 1
                            AND a.valID IN (SELECT Value
                                            FROM   Split(c.valID, ',')) ) )
WHERE  ordered = 1
       AND sageSOPOrderReturnLineID IS NOT NULL
       AND LEN(LTRIM(RTRIM(cnetprodid))) > 0
       AND cnetprodid LIKE 'S%'
       AND price > 10
       AND created > DATEADD(MONTH, -3, GETDATE())
GROUP  BY p.ProdID,
          p.CatID,
          a.prodID
HAVING SUM(qty) > 10
ORDER  BY SUM(qty) DESC 

Ich bekomme eine Zeile pro Produkt zurück, aber jetzt hat die Zeile mit 'S10381902' als ProdIDSpalte eine Zahl von 8820 für sumQty.

Ich möchte nur eine Zahl für die Anzahl der Produkte, die im letzten Quartal verkauft wurden, und nicht für Produkte, die weniger als 10 Einheiten verkauft haben, daher das HAVINGTeil.

Das COLLATEist da, weil die Tabellen aus verschiedenen Datenbanken stammen; eine ist in SQL_Latin1_General_CP1_CI_ASund eine andere Datenbank ist in Latin1_General_CI_AS.

Geige: http://sqlfiddle.com/#!3/ce1ed/4

Sean Airey
quelle

Antworten:

5

Das wahrscheinliche Problem besteht darin, dass durch das Verknüpfen mit diesen zusätzlichen Tabellen Zeilen in Anführungszeichen im Zwischenergebnis mehr als einmal dargestellt werden. Das heißt, Sie haben irgendwann einen Eins-zu-Viele-Beitritt. SQL Server fasst diese Zeilen dann gehorsam mehrmals zusammen. Es ist ein Fehler, der sehr leicht zu machen ist.

Die einfache Problemumgehung besteht darin, Ihre aggregierten Berechnungen durchzuführen, bevor Sie Eins-zu-Viele-Verknüpfungen durchführen. Es könnte ungefähr so ​​aussehen.

SELECT q.sumQty,
       p.ProdID,
       p.CatID
FROM (
        SELECT ProdID, SUM(qty) AS sumQty, ...other columns...
        FROM quoteitem
        GROUP BY ProdID
        HAVING SUM(qty) > 10
    ) q
       INNER JOIN cds_prod AS p
         ON p.ProdID COLLATE Latin1_General_CI_AS = cnetprodid
       INNER JOIN cds_atr AS a
         ON a.ProdID COLLATE Latin1_General_CI_AS = p.ProdID
       INNER JOIN lan_cat_sections AS c
         ON c.attID = a.atrID
             OR ( LEN(ISNULL(c.attID, '')) = 0
                  AND c.cat_id LIKE p.CatID + '%' )
                AND ( ( c.[include] = 0
                        AND a.valID NOT IN (SELECT Value
                                            FROM   Split(c.valID, ',')) )
                       OR ( c.[include] = 1
                            AND a.valID IN (SELECT Value
                                            FROM   Split(c.valID, ',')) ) )
WHERE  ordered = 1
       AND sageSOPOrderReturnLineID IS NOT NULL
       AND LEN(LTRIM(RTRIM(cnetprodid))) > 0
       AND cnetprodid LIKE 'S%'
       AND price > 10
       AND created > DATEADD(MONTH, -3, GETDATE())
GROUP  BY p.ProdID,
          p.CatID,
          a.prodID
ORDER  BY q.sumQty DESC 
db2
quelle