문제

나는 5tables:

고객 id-름

p_orders id-id_customer-코드 날짜

p_items id-id_order-설명-가격

고 h_orders 및 h_items,정확히의 사본 p_orders 및 p_items.

때 p_ 테이블 도달의 큰 금액을 행,이동 가장 오래된 h_ 테이블..그들은 때로는 역사.

그래서 내 문제입니다: 를 검색하는 방법 모두에서 데이터를 p_ 테이블과 h_ 고려하면 그들 중 하나로 고유한 테이블?

예를 들어,나를 검색하려는 수의 주문한 각각의 고객과의 총 가격(의 모든 고객의 주문고),내가 사용하는 쿼리:

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

그것은 작품이 단지 하나의'설정'의 테이블(p_ 또는 h_).그러나 나는 그들 모두.

나는 선택을 사용하는 유니온:

(
    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

이 하나의 작품이지만,경우에는 고객의 주문에서 모두 p_ 테이블 및에서 h_ 테이블,나는 2 개의 행하는 고객과 다른 2num_orders 및 total_money(각각에서 오는 p_ 테이블과 h_ 테이블)

나는 선택을 추가하여 그룹 id 외부 연합:

(
    --SELECT 2
)
UNION
(
    --SELECT 1
)
GROUP BY id
ORDER BY id ASC

하지만 쿼리 실패로 오류:구문 오류가 발생하거나"그룹에"문자 948, 것과 같은 그룹에 의해서 사용할 수 없습니다.

어떤 제안이 있으십니까?

편집:

에 대한 uriDium,그렇다,모든 테이블의 id 열로 기본 키가 언급된 필드(aka p_orders.id_customer)외국의 열쇠를 너무입니다.여기에서 테스트 db 구조를 덤프(추가 어떤 인덱스와 외국인 키 테이블을 생성,하지만 본 것을 의미):

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;
도움이 되었습니까?

해결책

두 테이블 위에 뷰를 만들어야 할 것입니다.

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

이제 그 견해에 참여할 수 있습니다. "ID"열이 무엇인지 알 수 있도록 유형 (P & H)을 포함 시켰습니다. 두 테이블의 ID ( "h"및 "p"가 복제를 가질 수 있다면 All_order_items보기에서 주문 테이블에 바로 결합해야합니다. 그렇지 않으면 두 뷰 사이에 많은 어려움을 겪게됩니다. 열은 지능적으로 설계되었으며 자동 침입 또는 아이덴티티 열뿐만 아니라.

다른 팁

당신은 이것을 시도 할 수 있습니다 :

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

두 쿼리의 결합이지만 집계 함수가없는 시야를 만듭니다. 동일한 레코드가 두 테이블에 있지 않으므로 Union을 모두 사용하여 서버가 필요하지 않습니다. 쿼리에서 두 테이블에 액세스하려는 다른 시간이 있습니다.

그런 다음보기를 사용하여 쿼리를 작성하십시오.

코드보기는 다음과 같습니다 (다른 목적으로 다른 필드를 원할 수도 있습니다.

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

그러면 쿼리 요청은 (이 중 어느 것도 조정이 필요하지 않을 수 있음)와 같은 것입니다.

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

내가 아는 한 SQL Server는 자동으로 복제를 제거해야합니다. Union을 사용하면 모두 복제물이 포함됩니다. SQL Server는 기본 키를 복제품을 해결하는 수단으로 사용한다고 생각합니다. 이 테이블의 기본 키는 동일한 데이터 유형으로 구성되며 P 테이블의 ID 1도 H 테이블의 ID 1입니까?

당신이보고있는 일을하는 가장 쉬운 방법은보기 ( "a_orders"및 "a_items")를 만드는 것입니다. 보기는 다음과 같이 정의됩니다.

SELECT * FROM p_orders
UNION
SELECT * FROM h_orders

a_orders에서 행을 h_orders에 삽입 할 때 행을 삭제하면 (주어진 순서가 두 테이블에 있지 않음) Union 대신 Union을 사용하는 것이 훨씬 더 효율적입니다.

감사에 대한 모든 대답니다.

모두 보기 방식'과'부질의 방법에 의해'지미 R.Houts 완벽하게 작동하고,어쩌면 전망은 단지 사용하기 더 편리..고 그들을 모두 취해야 한다 같은 시간(또는지?)

그래서 나는 답변으로 표시 첫 번째 중 하나에 대한 전망이다.

어쨌든,수있는 경우,당신 요청할 수 있습니다면 구조와 인덱스가 사용되는 좋은 또는 최적화할 수 있습?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top