SQL: Gruppierung 2 Tabellen 1 mit verbinden, verbindet, und dann?
Frage
Ich habe 5 Tabellen:
Kunden id - Name
p_orders id - id_customer - Code - Datum
p_items id - id_order - Beschreibung - Preis
und h_orders und h_items, die genau die Kopie p_orders und p_items sind.
Wenn die p_ Tabellen eine große Menge von Zeilen erreichen, bewegen i die älteste der h_ Tabellen .. sie durch die Geschichte.
Also, mein Problem ist: , wie die Daten von beiden p_ Tabellen abrufen und h_ sie als eine einzigartige Tabelle unter Berücksichtigung
Zum Beispiel, ich mag für jeden Kunden die Anzahl der Bestellungen abrufen und den Gesamtpreis ( aller Kundenaufträge ), und ich verwende diese Abfrage:
SELECT
customer.id,
customer.name,
count(DISTINCT p_orders.id) AS num_orders,
sum(p_items.price) AS total_money
FROM
customer
INNER JOIN p_orders ON p_orders.id_customer = customer.id
INNER JOIN p_items ON p_items.id_order = p_orders.id
GROUP BY
customer.id,
customer.name,
p_orders.id_customer
ORDER BY
customer.id
es funktioniert nur für eine 'Set' von Tabellen (p_ oder h _) .. aber ich möchte, dass sie beide.
Ich habe tryed eine UNION zu verwenden:
(
SELECT
customer.id,
customer.name,
count(DISTINCT p_orders.id) AS num_orders,
sum(p_items.price) AS total_money
FROM
customer
INNER JOIN p_orders ON p_orders.id_customer = customer.id
INNER JOIN p_items ON p_items.id_order = p_orders.id
GROUP BY
customer.id,
customer.name,
p_orders.id_customer
)
UNION
(
SELECT
customer.id,
customer.name,
count(DISTINCT h_orders.id) AS num_orders,
sum(h_items.price) AS total_money
FROM
customer
INNER JOIN h_orders ON h_orders.id_customer = customer.id
INNER JOIN h_items ON h_items.id_order = h_orders.id
GROUP BY
customer.id,
customer.name,
h_orders.id_customer
)
ORDER BY id ASC
Dies funktioniert, aber wenn ein Kunde bestellt hat sowohl in den p_ Tabellen und in den h_ Tabellen, werde ich habe 2 Reihen für diese Kunden mit 2 verschiedenen num_orders und total_money (jeweils von p_ Tabellen und h_ Tabellen kommen)
Ich habe tryed eine GROUP BY id außerhalb der Union hinzuzufügen:
(
--SELECT 2
)
UNION
(
--SELECT 1
)
GROUP BY id
ORDER BY id ASC
aber die Abfrage nicht mit ERROR: Syntaxfehlern bei oder in der Nähe von "GROUP" im Zeichen 948 , scheint wie GROUP BY nicht auf diese Weise verwendet werden kann,
.Jeder Vorschlag?
EDIT:
Für Uridium, ja, alle Tabellen haben die ID-Spalte als Primärschlüssel und die genannten Felder (auch bekannt als p_orders.id_customer) sind auch Fremdschlüssel. Hier ist der Test db Struktur Dump (i hinzugefügt einige Indizes und Fremdschlüssel nach der Erstellung von Tabellen, aber ich nicht denke, dass dies etwas bedeuten):
CREATE TABLE customer (
id serial NOT NULL,
name character(50)
);
CREATE TABLE p_orders (
id serial NOT NULL,
id_customer integer NOT NULL,
date date DEFAULT now(),
code character(5)
);
CREATE TABLE p_items (
id serial NOT NULL,
id_order integer NOT NULL,
descr character(250),
price money
);
CREATE TABLE h_orders (
id integer NOT NULL,
id_customer integer NOT NULL,
date date,
code character(5)
);
CREATE TABLE h_items (
id integer NOT NULL,
id_order integer NOT NULL,
descr character(250),
price money
);
CREATE UNIQUE INDEX id_h_orders ON h_orders USING btree (id);
CREATE INDEX id_h_o_c ON h_orders USING btree (id_customer);
CREATE UNIQUE INDEX id_items_h ON h_items USING btree (id);
CREATE INDEX id_ordinr_dsve ON h_items USING btree (id_order);
ALTER TABLE ONLY customer
ADD CONSTRAINT customer_pkey (id);
ALTER TABLE ONLY p_orders
ADD CONSTRAINT p_orders_pkey PRIMARY KEY (id);
ALTER TABLE ONLY p_items
ADD CONSTRAINT p_items_pkey PRIMARY KEY (id);
ALTER TABLE ONLY stats
ADD CONSTRAINT stats_pkey PRIMARY KEY (id);
ALTER TABLE ONLY p_orders
ADD CONSTRAINT "$1" FOREIGN KEY (id_customer) REFERENCES customer(id) ON DELETE CASCADE;
ALTER TABLE ONLY p_items
ADD CONSTRAINT "$1" FOREIGN KEY (id_order) REFERENCES p_orders(id) ON DELETE CASCADE;
ALTER TABLE ONLY h_orders
ADD CONSTRAINT "$1" FOREIGN KEY (id_customer) REFERENCES customer(id) ON DELETE CASCADE;
ALTER TABLE ONLY h_items
ADD CONSTRAINT "$1" FOREIGN KEY (id_order) REFERENCES h_orders(id) ON DELETE CASCADE;
Lösung
Sie sollten wahrscheinlich erstellen Blick auf die beiden Tabellen:
CREATE VIEW All_Orders
AS
SELECT
id,
id_customer,
code,
date,
'H' AS order_type
FROM
h_orders
UNION ALL
SELECT
id,
id_customer,
code,
date,
'P' AS order_type
FROM
p_orders
CREATE VIEW All_Order_Items -- A table name of "items" is pretty bad in my opinion
AS
SELECT
id,
id_order,
description,
price,
'H' AS order_item_type
FROM
h_items
UNION ALL
SELECT
id,
id_order,
description,
price,
'P' AS order_item_type
FROM
p_items
Jetzt können Sie nur auf diese Ansichten verbinden. Ich enthalten die Typen (P & H), so dass Sie wissen, was die „id“ -Spalte jetzt bezieht sich auf. Wenn die IDs in Ihren beiden Tabellen ( „h“ und „p“ Duplikate haben, dann werden Sie die Orders-Tabelle beitreten nach rechts in dem All_Order_Items anzuzeigen. Andernfalls werden Sie eine Menge Ärger zwischen den beiden Ansicht Beitritt haben. Hoffentlich Ihre ID Säulen sind intelligent gestaltet und nicht nur auto-incrmenting oder Identitätsspalten.
Andere Tipps
Sie könnten versuchen, diese:
SELECT tbl.ID,
tbl.Name,
sum(tbl.num_orders) num_orders,
sum(tbl.total_money) total_money
FROM (
SELECT customer.id,
customer.name,
count(DISTINCT p_orders.id) AS num_orders,
sum(p_items.price) AS total_money
FROM customer
INNER JOIN p_orders
ON p_orders.id_customer = customer.id
INNER JOIN p_items
ON p_items.id_order = p_orders.id
GROUP BY customer.id, customer.name, p_orders.id_customer
UNION
SELECT customer.id,
customer.name,
count(DISTINCT h_orders.id) AS num_orders,
sum(h_items.price) AS total_money
FROM customer
INNER JOIN h_orders
ON h_orders.id_customer = customer.id
INNER JOIN h_items
ON h_items.id_order = h_orders.id
GROUP BY customer.id, customer.name, h_orders.id_customer
) tbl
GROUB BY tbl.id, tbl.name
ORDER BY tbl.id ASC
Erstellen Sie eine Ansicht mit der Vereinigung der beiden Abfragen, aber ohne die Aggregatfunktionen. Nutzt Union Alle als denselben Datensatz ist nicht in beiden Tabellen, und Sie müssen den Server nicht Zeit zu verlieren suchen, um zu sehen that.You wird woanders vermutlich ein anderes Mal haben Sie in einer Abfrage beiden Tabellen zugreifen zu können.
Dann schreiben Sie Ihre Abfrage der Ansicht verwenden.
Ansicht Code wäre so etwas wie (Sie andere Felder für andere Zwecke mögen auch:
Create view customerOrders
AS
SELECT customer.id as CustomerID, customer.name, p_orders.id as OrderID, p_items.price as price
FROM customer
INNER JOIN p_orders ON p_orders.id_customer = customer.id
INNER JOIN p_items ON p_items.id_order = p_orders.id
union all
SELECT customer.id, customer.name, h_orders.id as id, H_items.price
FROM customer
INNER JOIN h_orders ON h_orders.id_customer = customer.id
INNER JOIN h_items ON h_items.id_order = h_orders.id
dann der Anruf für Ihre Abfrage so etwas wie wäre (nichts davon ist muß Einstellung geprüft)
SELECT CustomerID, customer.name, count(DISTINCT OrderID) AS num_orders,
sum(price) AS total_money
FROM customerOrders
GROUP BY CustomerID, customer.name
ORDER BY CustomerID
Soweit ich weiß, SQL Server automatisch Duplikate beseitigen sollte. Mit UNION werden nun alle Duplikate enthalten. Ich könnte mir vorstellen, dass SQL Server die Primärschlüssel als Mittel zur Ausarbeitung verwenden würde, was ein Duplikat ist. Sind die Primärschlüssel auf diesen Tabellen des gleichen Datentypen und ID 1 in Ihrer p Tabelle auch ID 1 in Ihrer h Tabelle aus?
Der einfachste Weg zu tun, was Sie suchen, wären Ansichten zu erstellen (sagen „a_orders“ und „a_items“). Die Ansichten würden wie definiert werden:
SELECT * FROM p_orders
UNION
SELECT * FROM h_orders
Wenn Sie Zeilen aus a_orders löschen, wie Sie sie zu h_orders einfügen (so eine bestimmte Reihenfolge in beiden Tabellen nicht wäre), wäre es ziemlich viel effizienter ALL UNION statt UNION zu verwenden.
Danke für alle Antworten, Jungs ..
Sowohl die Ansichten der Art und Weise "und der‚Unterabfrage Weg‘von Jimmie R. Houts funktioniert perfekt, vielleicht die Aussicht ist einfach bequeme .. zu verwenden und sie sollten beide die gleiche Zeit in Anspruch nehmen (oder nicht?)
Also ich werde als beste Antwort auf den ersten über die Ansichten markiert.
Wie auch immer, wenn ich kann, kann ich Sie fragen, ob die Struktur und die Indizes i verwendet eine gut sind oder könnte optimiert werden?