2010-02-15 45 views
5

Tôi khá là người ăn xin và tôi có hai bảng: "sản phẩm" và "thuộc tính sản phẩm".Chọn chống lại tập hợp con của danh sách trong MySQL

Dưới đây là một số dữ liệu ảo (những thứ thực tế liên quan đến bảng trở lên)

Sản phẩm Bảng: Các thuộc tính

product_id | product_name     
10   | aaa       
11   | bbb 
12   | ccc 

Sản phẩm Bảng:

attribute_id | product_id 
     21  | 10   
     23  | 10   
     24  | 10   
     21  | 11   
     24  | 11   
     21  | 12   
     25  | 12   

đâu mỗi sản phẩm có nhiều hơn một thuộc tính có thể . Tôi có danh sách các id thuộc tính như (21,10,25) và tôi cần chọn tất cả các sản phẩm có thuộc tính là tập hợp con của danh sách đó.

Có thể thực hiện việc này trong một truy vấn không?

Khi tôi lọc (21,24) đầu ra mong muốn là để trở về chỉ sản phẩm 11 (bbb)

Khi tôi lọc (21,23,24) đầu ra mong muốn là để mang các sản phẩm 10 và 11.

Khi tôi lọc (21) đầu ra mong muốn là không trả lại (vì tất cả các sản phẩm đều có ít nhất một thuộc tính khác).

Trả lời

5

Nếu bạn giả vờ rằng bộ lọc của bạn đang ở trong một bảng:

select * 
from product p 
where not exists (
    select 1 
    from attributes a 
    where a.product_id = p.product_id 
    and not exists(
     select 1 
     from filter f 
     where f.id_attribute = a.id_attribute)) 

Nếu đó là trong một truy vấn xây dựng:

select * 
from product p 
where not exists (
    select 1 
    from attributes a 
    where a.product_id = p.product_id 
    and attribute_id not in (<list>)) 

Đây là phần đầu của tôi, vì vậy có thể có lỗi chính tả.

+1

có, thứ hai hoạt động, cảm ơn bạn –

+0

Nó hoạt động cảm ơn bạn :) – Ashu

1

Giả sử bảng sản phẩm của bạn được gọi là sản phẩm và cột ID trong bảng đó chỉ được gọi là Mã sản phẩm:

SELECT * from Product p where p.Id IN 
    (Select id_product from ProductAttributes where id_attribute in (21, 23, 24)) 
+0

có nhưng cũng sẽ chọn các sản phẩm có một thuộc tính trong danh sách và sản phẩm khác không có trong danh sách. Tôi đã làm nó như thế.Tôi cần chúng để có tất cả các thuộc tính trong danh sách (như tôi đã nói), vì vậy mọi hàng có thể từ bảng thuộc tính với product_id –

1
select 
    P.id, 
    P.name, 
    count(P.id) as matched_attr_count, 
    count(PA.a_id) as total_attr_count 
from 
    product_attributes PA 
    left join product P on P.id = PA.p_id and PA.a_id in (21,23,24) 
group by 
    PA.p_id 
having 
    matched_attr_count = total_attr_count; 
+0

giải pháp này cũng có vẻ hoạt động ngoại trừ nó trả về nhiều hàng hơn cho mỗi sản phẩm để nó có lợi cho nhóm theo P. id_product in it chỉnh sửa: không, nó không hoạt động .. cùng một vấn đề, nó không lọc tất cả các thuộc tính của một sản phẩm, nó đủ cho một trong số chúng nằm trong danh sách –

+0

có nhưng cũng có khác vấn đề mà nó không lọc tất cả các thuộc tính –

+0

Tôi hiểu lầm bạn trước. Có vẻ như đã được sửa? – Qwerty

-1

cho tôi gửi dữ liệu tưởng tượng đơn giản (những thứ thực tế liên quan đến nhiều bảng)

bảng sản phẩm

product_id | product_name     
10   | aaa       
11  | bbb 

bảng product_attribute

attribute_id | product_id <br> 
21  | 10   
23  | 10   
24  | 10   
21  | 11   
24  | 11 

tôi muốn rằng:

  • khi tôi lọc cho (21,24) để được trả lại chỉ sản phẩm 11 (bbb)
  • khi tôi lọc cho (21,23,24) để được trả lại cả hai sản phẩm
  • khi tôi lọc cho (21) chỉ để được trả lại không (vì không có chuyên nghiệp ống có duy nhất mà thuộc tính)
+0

công cụ này là trong prestashop, nếu bạn cần một mô-đun để lọc theo thuộc tính , nhưng các bảng và quan hệ phức tạp hơn –

+1

Tôi khuyên bạn nên chỉnh sửa câu hỏi và thêm câu hỏi này vào câu hỏi. –

+1

Loại thông tin này phải được bao gồm trong câu hỏi ban đầu của bạn. Bạn có thể chỉnh sửa câu hỏi của mình nếu muốn sau này bao gồm thêm thông tin. Tôi đã chỉnh sửa câu hỏi của bạn cho bạn. –

1

này sẽ trả về chỉ những id nơi mà tất cả các thuộc tính cho mỗi id là hoàn toàn chứa trong danh sách:

select attribute_match.id_product from 
(select id_product, count(*) c from attributes 
    where id_attribute in (21, 10, 25) 
    group by id_product) attribute_match, 
(select id_product, count(*) c_count from attributes 
    group by id_product) attribute_total 
where attribute_match.id_product = attribute_total.id_product 
     and attribute_match.c = attribute_total.c 
+0

điều này không hoạt động trong trường hợp (21,23,24) (chỉ chọn 1 sản phẩm) –

+0

Tôi nghĩ truy vấn đã sửa đổi sẽ hoạt động - lựa chọn bên trong đầu tiên sẽ tạo ra 10,3 11,2 và lựa chọn bên trong thứ hai sẽ tạo ra 10 , 3 11,2 và do đó, lựa chọn bên ngoài phải phù hợp trên cả 10 và 11. – user273224

+0

có, bây giờ nó hoạt động, một cách dễ dàng hơn đã được đăng nhưng bạn stil nhận được một phiếu bầu –

1

Cho đến MySQL hỗ trợ sự kết hợp EXCEPT truy vấn,

SELECT product_id 
    FROM attributes 
    WHERE product_id NOT IN (
     SELECT product_id 
     FROM attributes 
     WHERE attribute_id NOT IN (21, 23, 24) 
    ) 
    GROUP BY product_id 
UNION 
SELECT id 
    FROM products AS p 
    LEFT JOIN attributes AS a 
    ON p.id = a.product_id 
    WHERE a.product_id IS NULL 

Nếu bạn muốn chỉ có các sản phẩm với tất cả các thuộc tính nhất định, thêm một điều khoản HAVING COUNT(*)=n với truy vấn bên ngoài đầu tiên, nơi 'n' là độ dài của danh sách thuộc tính.

+0

giống nhau, không hoạt động trong trường hợp (21,23,24) theo ví dụ của tôi –

+0

@Bogdan: mã gốc là dành cho câu hỏi sửa đổi 3. Cập nhật để phù hợp với phiên bản hiện tại (7). – outis

+0

Tôi không sửa đổi câu hỏi, chỉ giải thích tốt hơn với các ví dụ. Cảm ơn bạn đã nỗ lực, bạn có một phiếu bầu từ tôi –

0

Dựa trên kẻ hiểu biết của bạn, tôi được tối ưu hóa nó hơn nữa và chỉ dùng 1 COUNT địa chỉ tuyên bố như thế này:

SELECT * ,COUNT(p.product_id) AS c FROM product_attribute pa 
LEFT JOIN products p ON pa.product_id = p.product_id AND pa.attribute_id NOT IN ($filter_list) 
GROUP BY pa.product_id 
HAVING c=0 

Liệu nó hoạt động? :)

Chỉnh sửa:
Mã đó không trả về tên sản phẩm hoặc các trường khác mà nó có thể có. Đây là đúng:

SELECT * ,COUNT(pa.product_id) AS c FROM products p 
LEFT JOIN product_attribute pa ON pa.product_id = p.product_id AND pa.attribute_id NOT IN ($filter) 
GROUP BY p.product_id 
HAVING c=0 
Các vấn đề liên quan