2012-10-23 13 views
6

Ich gehe über einige Praxisfragen für eine Prüfung, die ich habe und ich habe ein Problem, die Gruppe vollständig zu verstehen. Ich sehe GROUP BY wie folgt: Gruppieren Sie das Ergebnis von einer oder mehreren Spalten.Probleme vollständig verstehen GROUP BY

Ich habe folgende Datenbankschema

enter image description here

enter image description here

Meine Anfrage

SELECT orders.customer_numb, sum(order_lines.cost_line), customers.customer_first_name, customers.customer_last_name 
FROM orders 
INNER JOIN customers ON customers.customer_numb = orders.customer_numb 
INNER JOIN order_lines ON order_lines.order_numb = orders.order_numb 
GROUP BY orders.customer_numb, order_lines.cost_line, customers.customer_first_name,  customers.customer_last_name 
ORDER BY order_lines.cost_line DESC 

Was ich strugg ling zu verstehen
Warum kann ich einfach nicht einfach GROUP BY orders.cost_line verwenden und die Daten nach cost_line gruppieren?

Was ich versuche zu erreichen
Ich mag würde den Namen des Kunden zu erreichen, die das meiste Geld ausgegeben hat. Ich verstehe einfach nicht ganz, wie ich das erreichen kann. Ich verstehe, wie Joins arbeiten, ich kann einfach nicht verstehen, warum ich nicht einfach GROUP BY customer_numb und cost_line (mit sum() verwendet, um den ausgegebenen Betrag zu berechnen). Ich scheine immer "keinen GROUP BY-Ausdruck" zu bekommen, wenn jemand erklären könnte, was ich falsch mache (nicht nur die Antwort), das wäre großartig - das würde ich wirklich schätzen und natürlich alle Ressourcen, die Sie haben GROUP mit richtig verwendet.

Entschuldigung für den langen Aufsatz und wenn ich etwas verpasst habe entschuldige ich mich. Jede Hilfe würde sehr geschätzt werden.

Antwort

4

Ich kann einfach nicht scheinen, meinen Kopf herum, warum kann ich nicht einfach GROUP BY customer_numb und cost_line (mit sum() verwendet, um die Menge ausgegeben zu berechnen).

Wenn Sie group by customer_numb sagen, Sie wissen, dass customer_numb eindeutig eine Zeile in der Kundentabelle identifiziert (unter der Annahme customer_numb ist entweder ein primärer oder alternativer Schlüssel), so dass eine bestimmtes customers.customer_numb man hat und nur ein Wert für customers.customer_first_name und customers.customer_last_name . Aber zur Zeit der Analyse weiß Oracle nichts oder verhält sich zumindest so, als ob es das nicht wüsste. Und es sagt, in ein bisschen Panik, "Was mache ich, wenn eine einzige customer_numb mehr als einen Wert für customer_first_name hat?"

Grob ist die Regel, Ausdrücke in der select Klausel können Ausdrücke in der group by Klausel verwenden und/oder Aggregatfunktionen verwenden. (Sowie Konstanten und Systemvariablen, die nicht von den Basistabellen abhängen, etc.) Und mit "verwenden" bezeichne ich den Ausdruck oder Teil des Ausdrucks. Wenn Sie also den Vornamen und den Nachnamen gruppieren, wäre customer_first_name || customer_last_name ebenfalls ein gültiger Ausdruck.

Wenn Sie eine Tabelle haben, wie customers und nach einem Primärschlüssel oder einer Spalte mit einem eindeutigen Schlüssel und Nicht-Null-Integritätsbedingung gruppieren, können Sie sie sicher in die group by-Klausel aufnehmen. In diesem speziellen Fall group by customer.customer_numb, customer.customer_first_name, customer.customer_last_name.

Beachten Sie auch, dass die order by in der ersten Abfrage fehlschlägt, da order_lines.cost_line hat keinen einzigen Wert für die Gruppe. Sie können auf sum(order_lines.cost_line) bestellen oder eine Spalte Alias ​​in der select Klausel und Ordnung auf diesem alias

SELECT orders.customer_numb, 
    sum(order_lines.cost_line), 
    customers.customer_first_name, 
    customers.customer_last_name 
FROM orders 
INNER JOIN customers ON customers.customer_numb = orders.customer_numb 
INNER JOIN order_lines ON order_lines.order_numb = orders.order_numb 
GROUP BY orders.customer_numb, 
    customers.customer_first_name, 
    customers.customer_last_name 
ORDER BY sum(order_lines.cost_line) 

oder

SELECT orders.customer_numb, 
    sum(order_lines.cost_line) as sum_cost_line, 
. . . 
ORDER BY sum_cost_line 

verwenden Hinweis: Ich habe gehört, dass einige RDBMSes zusätzliche Ausdrücke für die Gruppierung bedeuten wird ohne dass sie ausdrücklich erwähnt werden. Oracle gehört nicht zu diesen RDBMS.

Wie für die Gruppierung sowohl von customer_numb und cost_line einen DB mit zwei Kunden Betrachten, 1 und 2 mit zwei Aufträgen jeweils eine Zeile:

Customer Number | Cost Line 
       1 |  20.00 
       1 |  20.00 
       2 |  35.00 
       2 |  30.00 

select customer_number, cost_line, sum(cost_line) 
FROM ... 
group by customer_number, cost_line 
order by sum(cost_line) desc 

Customer Number | Cost Line | sum(cost_line) 
       1 |  20.00 |   40.00 
       2 |  35.00 |   35.00 
       2 |  30.00 |   30.00 

Die erste Zeile mit dem höchsten sum(cost_line) ist nicht der Kunde, der die verbrauchte die meisten.

+0

Sehr beschreibende Antwort. Ich schätze die ganze Zeit, danke. –

2

Ich verstehe, wie verbindet Arbeit, ich kann meinen Kopf nicht scheinen um zu bekommen, warum kann ich nicht einfach GROUP BY customer_numb und cost_line (mit sum() verwendet, um den Betrag ausgegeben zu berechnen).

Dies sollte Ihnen die Summe für jeden Kunden geben.

SELECT orders.customer_numb, sum(order_lines.cost_line) 
FROM orders 
INNER JOIN order_lines ON order_lines.order_numb = orders.order_numb 
GROUP BY orders.customer_numb 

Beachten Sie, dass jede Spalte in der SELECT-Klausel, die nicht ein Argument für eine Aggregatfunktion ist, ist auch eine Spalte in der GROUP BY-Klausel.

Jetzt können Sie das mit anderen Tabellen verbinden, um mehr Details zu erhalten. Hier ist eine Möglichkeit, einen gemeinsamen Tabellenausdruck zu verwenden. (Es gibt auch andere Möglichkeiten, um auszudrücken, was Sie wollen.)

with customer_sums as (
    -- We give the columns useful aliases here. 
    SELECT orders.customer_numb as customer_numb, 
      sum(order_lines.cost_line) as total_orders 
    FROM orders 
    INNER JOIN order_lines ON order_lines.order_numb = orders.order_numb 
    GROUP BY orders.customer_numb 
) 
select c.customer_numb, c.customer_first_name, c.customer_last_name, cs.total_orders 
from customers c 
inner join customer_sums cs 
on cs.customer_numb = c.customer_numb 
order by cs.total_orders desc 

Warum kann ich nicht einfach verwenden nur GROUP BY orders.cost_line und Gruppe die Daten von cost_line?

Wenn Sie GROUP BY auf order_lines.cost_line anwenden, erhalten Sie eine Zeile für jeden einzelnen Wert in order_lines.cost_line. (Die Spalte orders.cost_line existiert nicht.) So könnten diese Daten aussehen.

OL.ORDER_NUMB OL.COST_LINE O.CUSTOMER_NUMB C.CUSTOMER_FIRST_NAME C.CUSTOMER_LAST_NAME 
-- 
1    1.45   2014   Julio     Savell 
1    2.33   2014   Julio     Savell 
1    1.45   2014   Julio     Savell 
2    1.45   2014   Julio     Savell 
2    1.45   2014   Julio     Savell 
3    13.00  2014   Julio     Savell 

Sie können Gruppe von order_lines.cost_line, aber es wird Ihnen keine nützlichen Informationen. Diese Abfrage

select order_lines.cost_line, orders.customer_numb 
from order_lines 
inner join orders on orders.customer_numb = order_lines.customer_numb 
group by order_lines.cost_line; 

sollte etwas wie diese zurückgeben.

OL.COST_LINE O.CUSTOMER_NUMB 
-- 
1.45   2014 
2.33   2014 
13.00  2014 

nicht besonders nützlich.

Wenn Sie an der Summe der Auftragspositionen interessiert sind, müssen Sie entscheiden, welche Spalte oder Spalten zu gruppieren (zusammenzufassen) von. Wenn Sie nach Bestellnummer gruppieren (zusammenfassen), erhalten Sie drei Zeilen. Wenn Sie nach Kundennummer gruppieren (zusammenfassen), erhalten Sie eine Zeile.