2010-06-29 40 views
16

đơn giản và câu hỏi nhanh, tôi có những bảng:Nội tham gia với count() trên ba bảng

//table people 
| pe_id | pe_name | 
| 1 | Foo | 
| 2 | Bar | 
//orders table 
| ord_id | pe_id | ord_title | 
| 1 | 1 | First order | 
| 2 | 2 | Order two | 
| 3 | 2 | Third order | 
//items table 
| item_id | ord_id | pe_id | title | 
| 1  | 1 | 1 | Apple | 
| 2  | 1 | 1 | Pear | 
| 3  | 2 | 2 | Apple | 
| 4  | 3 | 2 | Orange | 
| 5  | 3 | 2 | Coke | 
| 6  | 3 | 2 | Cake | 

tôi cần phải có một truy vấn danh sách tất cả những người, đếm số lượng các đơn đặt hàng và các tổng số mặt hàng, như vậy:

| pe_name | num_orders | num_items | 
| Foo | 1  | 2  | 
| Bar | 2  | 4  | 

Nhưng tôi không thể làm cho nó hoạt động! tôi đã cố gắng

SELECT 
    people.pe_name, 
    COUNT(orders.ord_id) AS num_orders, 
    COUNT(items.item_id) AS num_items 
FROM 
    people 
    INNER JOIN orders ON (orders.pe_id = people.pe_id) 
    INNER JOIN items ON items.pe_id = people.pe_id 
GROUP BY 
    people.pe_id; 

Nhưng điều này trả về num_* giá trị không đúng:

| name | num_orders | num_items | 
| Foo | 2  | 2  | 
| Bar | 8  | 8  | 

tôi nhận thấy rằng nếu tôi cố gắng để tham gia vào một bảng lúc, nó hoạt động:

SELECT 
    people.pe_name, 
    COUNT(orders.ord_id) AS num_orders 
FROM 
    people 
    INNER JOIN orders ON (orders.pe_id = people.pe_id) 
GROUP BY 
    people.pe_id; 

//give me: 
| pe_name | num_orders | 
| Foo  |   1 | 
| Bar  |   2 | 

//and: 
SELECT 
    people.pe_name, 
    COUNT(items.item_id) AS num_items 
FROM 
    people 
    INNER JOIN items ON (items.pe_id = people.pe_id) 
GROUP BY 
    people.pe_id; 
//output: 
| pe_name | num_items | 
| Foo  |   2 | 
| Bar  |   4 | 

Làm thế nào để kết hợp hai truy vấn trong một?

+1

Bàn của bạn thực sự cần phải được tổ chức lại. Bảng mục không nên tham chiếu bảng thứ tự và chắc chắn không phải bảng người, và bạn cần một bảng mới cho mối quan hệ nhiều-nhiều, như các đơn đặt hàng và các mục. –

+0

Tại sao anh ta cần nhiều người đến nhiều nếu một mệnh lệnh chỉ có thể thuộc về một người. Mô hình của ông có ý nghĩa hoàn hảo. –

+0

@adam: tôi không hiểu đề xuất của bạn. Sau đó, chỉ id vô dụng mà tôi thấy là pe_id vào bảng mục, nhưng có thể có thể hữu ích trong tương lai để có được tổng số mục của một người mà không cần tham gia bảng đơn đặt hàng. Ý của bạn là gì với "Bảng mục không nên tham chiếu thứ tự"? – Strae

Trả lời

27

Đó là ý nghĩa hơn để tham gia các mục với các đơn đặt hàng hơn cho người dân!

SELECT 
    people.pe_name, 
    COUNT(distinct orders.ord_id) AS num_orders, 
    COUNT(items.item_id) AS num_items 
FROM 
    people 
    INNER JOIN orders ON orders.pe_id = people.pe_id 
     INNER JOIN items ON items.ord_id = orders.ord_id 
GROUP BY 
    people.pe_id; 

Tham gia các mục có người kích động nhiều gấp đôi. Ví dụ: các mặt hàng bánh theo thứ tự 3 sẽ được liên kết với đơn đặt hàng 2 thông qua sự tham gia giữa mọi người và bạn không muốn điều này xảy ra !!

Vì vậy:

1- Bạn cần hiểu rõ sơ đồ của mình. Các mục là liên kết đến các đơn đặt hàng chứ không phải cho mọi người.

2- Bạn cần phải tính các đơn hàng riêng biệt cho một người, nếu không bạn sẽ tính nhiều mục như đơn hàng.

+0

Điều này có ý nghĩa hơn, nhưng với lược đồ hiện tại, nó sẽ không tạo ra sự khác biệt. –

+0

"Các mục là liên kết đến các đơn đặt hàng và không cho mọi người" .. đồng ý, nhưng pe_id trên bảng mục cho phép tôi, ví dụ, truy xuất tất cả các mục cho 1 người mà không tham gia bảng đơn đặt hàng .. có thể hữu ích, có thể, và nếu không, tôi có thể dễ dàng loại bỏ chỉ mục trong bước tối ưu hóa cuối cùng;) – Strae

+0

không xóa pe_id của bảng mục, nó có thể là một lối tắt tốt cho một số truy vấn. NHƯNG cho điều này đặc biệt, nó chỉ là không hữu ích! –

1

Giải pháp của bạn gần như chính xác. Bạn có thể thêm DISTINCT:

SELECT 
    people.pe_name, 
    COUNT(distinct orders.ord_id) AS num_orders, 
    COUNT(items.item_id) AS num_items 
FROM 
    people 
    INNER JOIN orders ON (orders.pe_id = people.pe_id) 
    INNER JOIN items ON items.pe_id = people.pe_id 
GROUP BY 
    people.pe_id; 
+0

Không cho kết quả tốt. | tên | num_orders | num_items | | Foo | 1 | 2 | | Bar | 2 | 8 | –

+0

Có, điều này cho phép đếm số lượng mặt hàng rong, bạn nên thêm mệnh đề 'khác biệt 'trong số đếm (mục) và sau đó làm việc – Strae

4

Như Frank đã chỉ ra, bạn cần sử dụng DISTINCT. Ngoài ra, kể từ khi bạn đang sử dụng các phím composite tiểu học (đó là hoàn toàn tốt đẹp, BTW), bạn cần phải chắc chắn rằng bạn sử dụng toàn bộ quan trọng trong tham gia của bạn:

SELECT 
    P.pe_name, 
    COUNT(DISTINCT O.ord_id) AS num_orders, 
    COUNT(I.item_id) AS num_items 
FROM 
    People P 
INNER JOIN Orders O ON 
    O.pe_id = P.pe_id 
INNER JOIN Items I ON 
    I.ord_id = O.ord_id AND 
    I.pe_id = O.pe_id 
GROUP BY 
    P.pe_name 

Without I.ord_id = O.ord_id nó được tham gia mỗi mục hàng vào mỗi hàng đơn hàng cho một người.

1
select pe_name,count(distinct b.ord_id),count(c.item_id) 
from people a, order1 as b ,item as c 
where a.pe_id=b.pe_id and 
b.ord_id=c.order_id group by a.pe_id,pe_name 
+0

Cảm ơn bạn đã cập nhật Bo Persson –

3

tôi đã cố gắng đặt biệt trên cả hai, count (ord.ord_id riêng biệt) như num_order, count (biệt items.item_id) như các mục num

làm việc của nó :)

SELECT 
     people.pe_name, 
     COUNT(distinct orders.ord_id) AS num_orders, 
     COUNT(distinct items.item_id) AS num_items 
    FROM 
     people 
     INNER JOIN orders ON (orders.pe_id = people.pe_id) 
     INNER JOIN items ON items.pe_id = people.pe_id 
    GROUP BY 
     people.pe_id; 

Cảm ơn Chủ đề nó giúp :)

0

Một trong những nhu cầu cần hiểu JOIN hoặc một loạt JOIN là gì đối với một tập hợp dữ liệu.Với bài đăng của strae, một pe_id của 1 được kết hợp với thứ tự và các mục tương ứng trên pe_id = 1 sẽ cung cấp cho bạn dữ liệu sau để "chọn" từ:

[table people section] [table orders section] [table items section] ]

| people.pe_id | people.pe_name | orders.ord_id | orders.pe_id | orders.ord_title | item.item_id | item.ord_id | item.pe_id | item.title |

| 1 | Foo | 1 | 1 | Thứ tự đầu tiên | 1 | 1 | 1 | Apple |
| 1 | Foo | 1 | 1 | Thứ tự đầu tiên | 2 | 1 | 1 | Lê |

Tham gia cơ bản sẽ đưa ra một sản phẩm Descartes của tất cả các bảng. Về cơ bản, bạn có tập dữ liệu đó để chọn và đó là lý do tại sao bạn cần có số lượng riêng biệt trên orders.ord_id và items.item_id. Nếu không, cả hai số đếm sẽ dẫn đến 2 - bởi vì bạn có 2 hàng để chọn.

Các vấn đề liên quan