2016-07-13 17 views
0

Ich normalisiere einige Tabellen und habe ein Problem gelöst, das ich nicht lösen kann.Gruppe nach Ergebnis der bedingten Unterabfrage

Die alte, nicht-normalisierte Abfrage sieht wie folgt aus:

SELECT 
     SUM(allorderlines.COUNT), 
     products.NAME, 
     products.VOLUME, 
     people.NAME, 
     people.ID, 
     layout.POSTYPE, 
     IF(allorders.TOTAL = allorders.DISCOUNT, 1, 0) AS ISFREE 
    FROM 
     allorderlines 
     INNER JOIN allorders 
      ON allorderlines.ORDERID = allorders.ORDERID 
      INNER JOIN people 
       ON allorders.EMPLOYEE = people.ID 
      INNER JOIN layout 
       ON allorders.POSID = layout.ID 
     INNER JOIN products 
      ON allorderlines.PRODUCT = products.ID 
    WHERE 
     allorderlines.PRODUCT = ? 
    GROUP BY 
     people.ID, 
     layout.POSTYPE, 
     ISFREE 
    ORDER BY 
     layout.POSTYPE ASC, 
     people.NAME, 
     ISFREE ASC, 
     products.NAME 

Das bedeutet, kann ich meine Gruppe Ergebnisse in, ob die Aufträge frei waren (das heißt kostenlos) oder nicht.

In meiner normalisierten Version habe ich keine Summe der Reihenfolge in der Tabelle allorders verfügbar (allorders.TOTAL und allorders.DISCOUNT). Um herauszufinden, ob eine Bestellung frei ist, muss ich SUM(allorderlines.LINEPRICE) und sehen, ob es gleich 0 ist. Die Zeile für das Produkt wird nicht 0 sein, aber eine andere Zeile mit dem diskontierten Wert der Bestellung wird vorhanden sein und der der Summe entsprechen von Produkten, wenn der Auftrag insgesamt frei war: so wie diese:

#Order 23123 
Line 1: 2000 
Line 2: 1000 
Line 3 (discount): -3000 

Free: true 

#Order 23124 
Line 1: 2000 
Line 2: 1000 
Line 3 (discount): -2000 

Free: false 

ich kann nicht herausfinden, wie dies zu tun und halten über Logik. Mein engstener Versuch wurde anstelle die Linie für ISFREE mit so etwas wie:

IF(SUM(allorderlines.LINEPRICE) = 0,1,0) AS ISFREE 

Aber das gibt mir einen „kann nicht Gruppe von ISFREE“ -Fehler, vermutlich, weil ich zu einer Gruppe in der nicht zur Verfügung versuchen auf etwas, das ist Lage.

Eine offensichtliche Lösung wäre, die Summe von allorders.LINEPRICE in der allorders-Tabelle zu speichern, aber das wäre überflüssig, und ich versuche, davon wegzukommen.

Beachten Sie, dass der DISCOUNT-Wert zuvor positiv war, wo er als Bestellposten jetzt negativ ist. Daher (allorders.TOTAL = allorders.DISCOUNT) = FREE.

EDIT: Um zu klären, die Ergebnismenge etwas aussehen soll:

people.ID  people.NAME SUM(COUNT)  POSTYPE ISFREE 
3    A name   4    1   1 
3    A name   24    1   0 
3    A name   2    2   1 
3    A name   7    2   0 
6    Another name 2    1   1 
6    Another name 93    1   0 
6    Another name 6    2   1 
6    Another name 193    2   0 

Jede Person 0-4 Zeilen kann zu jedem Preis zu jeder POSTYPE für das jeweilige Produkt und 4 verkauft, 0 bedeutet nichts das bedeutet mindestens 1 frei und 1 verkauft für beide POSTYPEN (wie zum Zeitpunkt des Schreibens gibt es nur 2 Arten).

Antwort

1

Lassen Sie uns zuerst dies tun. Sie sehen, nach irgendwelchen Aufträgen zu suchen, die ein bestimmtes Produkt haben. Machen Sie eine Vorabfrage, um alle eindeutigen Bestellungen mit diesem Produkt zu erhalten. Fügen Sie dann hinzu, um nach der Bestellung gruppierte Zeilen für die gesamte Nettobestellung zu bestellen, um frei zu ermitteln.

Schließlich wieder mit den Auftrag Zeilen und Rest der Tabellen für die Extras, die Sie suchen, aber die Gruppe von Menschen, Layout, ist frei Flagge, aber die Bestellung durch den Produktnamen impliziert, dass alle anzeigen Produktnamen für die Bestellung, aber Ihre Where-Klausel sucht nur nach dem EINEN Produkt.

Die ersten Dinge jedoch, präqualifizierende Abfrage und auch mit Alias-Namen vs lange Tabellennamen.

SELECT 
     QualByProd.OrderID, 
     SUM(AOL2.LinePrice) as TotalOrder, 
     COUNT(*) as LineItemCount 
    FROM 
     (SELECT distinct AOL.OrderID 
      from AllOrderLines AOL 
      where AOL.Product = ?) QualByProd 
     JOIN AllOrderLines AOL2 
      ON QualByProd.OrderID = AOL2.OrderID2 
    GROUP BY 
     QualByProd.OrderID 

Diese Ihnen jeden Auftrag gibt, dass 1) die Produkt-ID in Frage hat, und 2) Zusammenfassung aller Einzelposten aus dem gesamten Auftrag freien Status oder wer oder sogar Produktnamen zusammengefasst, unabhängig davon. Aber an diesem Punkt ist es ein Datensatz pro qualifizierter Bestellung mit einer Gesamtsumme (einschließlich einer Zählung der gesamten Werbebuchungen in der Reihenfolge, die mit dem qualifizierenden Produkt verknüpft sind). Jetzt können wir diese gesamte Abfrage als Grundlage für Ihr Original verwenden, wie ...

SELECT 
     PR.NAME ProductName, 
     PR.VOLUME ProductVolume, 
     P.NAME PersonName, 
     P.ID PersonID, 
     L.POSTYPE, 
     IF(OkRecs.TotalOrder, 1, 0) AS ISFREE, 
     OkRecs.LineItemCount 
    FROM 
     (entire first query above by product) as OkRecs 
     JOIN AllOrderLines AOL3 
      ON OkRecs.OrderID = AOL3.OrderID 
     JOIN AllOrders AO 
      ON OkRecs.OrderID = AO.OrderID 
      INNER JOIN people P 
       ON AO.EMPLOYEE = P.ID 
      INNER JOIN layout L 
       ON AO.POSID = L.ID 
     INNER JOIN products PR 
      ON AOL3.Product = PR.ID 
    WHERE 
     AOL3.PRODUCT = ? 
    ORDER BY 
     L.POSTYPE, 
     P.NAME, 
     IF(OkRecs.TotalOrder, 1, 0) 
     PR.NAME 

Jetzt zeigt Ihre Gruppierung Aggregationen an, aber ich glaube nicht, dass Sie das wollen. Du könntest eine Person mit zwei verschiedenen Aufträgen haben ... 1 frei, 5 bezahlt etwas, insgesamt 6 Bestellungen. Da keine Zuschlagstoffe vorhanden sind, können Sie einfach nachbestellen. Endlich die Free-Items. Wenn Sie alle Aufträge sehen möchten, die FIRST frei sind, dann verschieben Sie innerhalb des POSType, der Person und des Produkts den IF() an die erste Position.

+0

Gerade als ich ins Bett ging. Ich schaue mir das morgen an. Vielen Dank! – nickdnk

+0

Das gibt mir Zehntausende von Zeilen und der Zeilenzähler ist falsch. Wenn ich am Ende auf L.POSTYPE, P.ID eine Gruppe hinzufüge, bekomme ich eine vernünftigere Menge an Zeilen, aber die Summe der Zeilenanzahl ist immer noch falsch. Ich benötige die Gesamtmenge der verkauften Artikel für eine Person an einem POSTYPE (layout.POSTYPE), gruppiert, ob die fragliche Bestellung frei war oder nicht. – nickdnk

+0

Siehe aktualisierte Frage mit Beispiel. – nickdnk

Verwandte Themen