2016-04-21 9 views
2

das folgende Szenario vor:Wie MAX über SUMs MySQL finden

an Item has a Price 

a Order contains Items 

a Delivery contains Orders 

Ich möchte für jede Lieferung abfragen, die Bestellung mit dem höchsten Preis, falls der Preis einer Bestellung die Summe der Preise für die ist enthaltene Gegenstände.

Ein einfaches ausreichend Schema würde wie folgt aussehen:

Lieferung

D_ID

Bestellen

O_ID

Artikel

I_ID, Preis

ItemsInOrder

O_ID, I_ID

OrdersInDelivery

D_ID, O_ID

ich in dem Punkt, steckte die Summe Ergebnisse zu haben, um die maximale Bestellmenge pro Lieferung zu erhalten:

SELECT d_id,o_id,SUM(price) 
from ItemsInOrder 
natural join OrdersInDelivery 
natural join Item 
group by d_id,o_id 

Wie soll ich von hier aus gehen zu bekommen dass jedes d_id einmal und neben der o_id mit der maximalen Preissumme erscheint?

+0

Subquery mit SUM und dann SELECT MAX() auf sie. – i486

+0

Wenn Sie möchten, sollten Sie diese einfache Vorgehensweise in zwei Schritten befolgen: 1. Wenn Sie dies noch nicht getan haben, stellen Sie geeignete DDLs (und/oder eine SQL-Datenbank) bereit, damit wir das Problem leichter replizieren können. 2. Wenn Sie dies noch nicht getan haben, geben Sie ein gewünschtes Ergebnisset ein, das den Informationen in Schritt 1 entspricht. – Strawberry

+0

Und was möchten Sie, wenn zwei Lieferungen denselben Höchstpreis haben? –

Antwort

0

Danke, aber keiner von ihnen war das, was ich suchte. Schließlich fand ich, was ich suchte und der Ansatz i wählen Sie wie folgt vor:

SELECT d_id,o_id,sum_price 
FROM (
    SELECT d_id,o_id,SUM(price) as sum_price 
    from ItemsInOrder 
    natural join OrdersInDelivery 
    natural join Item 
    group by d_id,o_id 
    order by d_id,sum_price desc 
) as sums 
GROUP BY d_id 
+2

Dies ist sehr falsch, um GROUP BY zu verwenden. In diesem Fall kann der Server einen beliebigen Wert aus jeder Gruppe auswählen. Wenn sie also nicht identisch sind, sind die ausgewählten Werte unbestimmt, was wahrscheinlich nicht Ihren Vorstellungen entspricht. Laut MySQL-Dokument ion: http://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html –

+2

Siehe diese Antwort: http://StackOverflow.com/A/18710186 –

+1

@ OneManCrew Danke für die Heads-up, das war ein sehr interessanter Gedanke, in anderen Fällen magst du Recht haben, aber in diesem Fall, soweit ich verstehe, sollte es funktionieren, da sum_price funktional abhängig von d_id, o_id ist und von ihnen eindeutig bestimmt werden kann. Dies ist nicht der Fall, den Sie in dem von Ihnen angegebenen Link angegeben haben. –

0

Verwenden Sie nicht natural join. Sie sind ein Fehler, der darauf wartet, ausgeführt zu werden, da sie von den Namen der Spalten in den Tabellen abhängig sind - nicht einmal mit richtig und explizit definierten Fremdschlüsselbeziehungen. Verwenden Sie stattdessen on oder using.

Diese Art der Abfrage ist in MySQL schmerzhaft, weil MySQL keine CTEs (common table expressions) unterstützt und auch keine Fensterfunktionen unterstützt. So ist die Abfrage komplizierter als in anderen Datenbanken:

select oid.d_id, o_id, SUM(price) 
from OrdersInDelivery oid join 
    ItemsInOrder iio 
    using (o_id) 
    Item i 
    using (i_id) 
group by d_id, o_id 
having sum(price) = (select sum(iio2.price) 
        from ItemsInOrder iio2 join 
          Item i2 
          using (i_id) 
        where iio2.d_id = iio.d_id 
        group by iio2.o_id 
        order by sum(iio2.price) desc 
        limit 1 
        ); 
+0

Wie wäre es, die Ergebnisse der Abfrage in der ursprünglichen Frage in einer temporären Tabelle zu definieren und dann in der Max-Abfrage zu verwenden? –

+0

Ich bevorzuge nicht temporäre Tabellen zu verwenden, es sei denn, absolut notwendig. In diesem Fall vereinfacht es die Abfrage und - wenn Sie einen Index hinzufügen - macht es wahrscheinlich auch schneller. –

0

ich die Ergebnisse bin zu teilen, die ich habe, so weit, so jemand, den Sie fortsetzen könnte helfen, weil ich jetzt zum Flughafen verlassen müssen :) I Ich werde versuchen, es morgen noch einmal zu überprüfen, falls niemand es herausfinden sollte.

es ist eine herausfordernde Frage Jungs.

ich haben bereits einige Beispiele hier: http://sqlfiddle.com/#!9/d4fed2

Und die letzte Abfrage i tat

SELECT d_id,OID.o_id,sumPrice 
from OrdersInDelivery OID 
join (SELECT IIO.o_id,SUM(I.price) as sumPrice 
from ItemsInOrder IIO 
join item I on I.i_id = IIO.i_id 
group by IIO.o_id) IIO1 on OID.o_id = IIO1.o_id 

Viel Glück :)

2

Sie mit sich selbst verwenden können Links Joining, zwicken Join Bedingungen und Filter. Bei diesem Ansatz verlassen Sie die Tabelle mit sich selbst. Gleichheit geht natürlich in der Gruppenkennung.

SELECT a.* 
FROM (
     SELECT oid.d_id AS d_id, o_id, SUM(price) AS sum_price 
     FROM `OrdersInDelivery` oid 
     INNER JOIN `ItemsInOrder` iio USING (o_id) 
     INNER JOIN `Item` i USING (i_id) 
     GROUP BY d_id, o_id 
    ) a 
LEFT OUTER JOIN (
        SELECT oid.d_id AS d_id, o_id, SUM(price) AS sum_price 
        FROM `OrdersInDelivery` oid 
        INNER JOIN `ItemsInOrder` iio USING (o_id) 
        INNER JOIN `Item` i USING (i_id) 
        GROUP BY d_id, o_id 
       )b 
    ON a.d_id = b.d_id AND a.sum_price < b.sum_price 
WHERE b.d_id IS NULL AND b.o_id IS NULL; 

einen Blick auf diese Abfrage in SQL Geige Nehmen: http://sqlfiddle.com/#!9/d5c04d/1

In diesem Fall ist es empfehlenswert, TEMPORARY TABLE zu verwenden: für alle Ihre Antworten

CREATE TEMPORARY TABLE OrderSummary(
    SELECT oid.d_id AS d_id, o_id, SUM(price) AS sum_price 
      FROM `OrdersInDelivery` oid 
      INNER JOIN `ItemsInOrder` iio USING (o_id) 
      INNER JOIN `Item` i USING (i_id) 
      GROUP BY d_id, o_id 
    ); 
CREATE TEMPORARY TABLE OrderSummary2(
    SELECT * FROM OrderSummary 
    ); 

    SELECT a.* 
    FROM OrderSummary a 
    LEFT OUTER JOIN OrderSummary2 b 
     ON a.d_id = b.d_id AND a.sum_price < b.sum_price 
    WHERE b.d_id IS NULL AND b.o_id IS NULL; 
+0

Danke für die Antwort, aber dieser Ansatz fügt eine unnötige Join-und Code-Komplexität, und auch eine temporäre Tabelle kann zu Leistungsproblem wegen der Verlust eines richtigen Index führen. –