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;
War es hilfreich?

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?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top