CHỌN DISTINCT trên một cột, trong khi trả về các cột khác?


12

Tôi có một truy vấn sử dụng ba bảng tra cứu để có được tất cả thông tin tôi cần. Tôi cần phải có DISTINCTcác giá trị cho một cột, tuy nhiên tôi cũng cần phần còn lại của dữ liệu được liên kết với nó.

Mã SQL của tôi:

SELECT acss_lookup.ID AS acss_lookupID,
   acss_lookup.product_lookupID AS acssproduct_lookupID,
   acss_lookup.region_lookupID AS acssregion_lookupID,
   acss_lookup.document_lookupID AS acssdocument_lookupID,
   product.ID AS product_ID,
   product.parent_productID AS productparent_product_ID,
   product.label AS product_label,
   product.displayheading AS product_displayheading,
   product.displayorder AS product_displayorder,
   product.display AS product_display,
   product.ignorenewupdate AS product_ignorenewupdate,
   product.directlink AS product_directlink,
   product.directlinkURL AS product_directlinkURL,
   product.shortdescription AS product_shortdescription,
   product.logo AS product_logo,
   product.thumbnail AS product_thumbnail,
   product.content AS product_content,
   product.pdf AS product_pdf,
   product.language_lookupID AS product_language_lookupID,
   document.ID AS document_ID,
   document.shortdescription AS document_shortdescription,
   document.language_lookupID AS document_language_lookupID,
   document.document_note AS document_document_note,
   document.displayheading AS document_displayheading
FROM acss_lookup
     INNER JOIN product ON (acss_lookup.product_lookupID = product.ID)
     INNER JOIN document ON (acss_lookup.document_lookupID = document.ID)
ORDER BY product_displayheading ASC;

Tôi muốn nhận tất cả các sản phẩm từ truy vấn này nhưng tôi chỉ muốn nhận chúng một lần vì tôi đang điền một menu thả xuống cho một ứng dụng tìm kiếm. Tôi muốn người dùng có thể chọn từ các sản phẩm trong bảng đó (đó là lý do tại sao tôi chỉ cần chúng một lần).

Đây có phải là quá phức tạp? Tôi có nên sử dụng một cách tiếp cận đơn giản hơn?


Nhưng một sản phẩm có liên quan đến nhiều tài liệu. Và truy vấn của bạn trả về tất cả (tài liệu cho một sản phẩm). Nên chọn cái nào?
ypercubeᵀᴹ

Câu trả lời:


6

Một cách tiếp cận khác chưa được đề cập là sử dụng các hàm của cửa sổ, ví dụ row_number:

   SELECT * FROM  
   (
   SELECT acss_lookup.ID AS acss_lookupID, 
   ROW_NUMBER() OVER 
   (PARTITION BY your_distinct_column ORDER BY any_column_you_think_is_appropriate)
   as num,
   acss_lookup.product_lookupID AS acssproduct_lookupID,
   acss_lookup.region_lookupID AS acssregion_lookupID,
   acss_lookup.document_lookupID AS acssdocument_lookupID,
   product.ID AS product_ID,
   product.parent_productID AS productparent_product_ID,
   product.label AS product_label,
   product.displayheading AS product_displayheading,
   product.displayorder AS product_displayorder,
   product.display AS product_display,
   product.ignorenewupdate AS product_ignorenewupdate,
   product.directlink AS product_directlink,
   product.directlinkURL AS product_directlinkURL,
   product.shortdescription AS product_shortdescription,
   product.logo AS product_logo,
   product.thumbnail AS product_thumbnail,
   product.content AS product_content,
   product.pdf AS product_pdf,
   product.language_lookupID AS product_language_lookupID,
   document.ID AS document_ID,
   document.shortdescription AS document_shortdescription,
   document.language_lookupID AS document_language_lookupID,
   document.document_note AS document_document_note,
   document.displayheading AS document_displayheading
   FROM acss_lookup
     INNER JOIN product ON (acss_lookup.product_lookupID = product.ID)
     INNER JOIN document ON (acss_lookup.document_lookupID = document.ID)
   )a
   WHERE a.num = 1
   ORDER BY product_displayheading ASC;

@ a1ex07- Cảm ơn! Điều đó đã làm việc. Mỗi lần tôi cố gắng điều chỉnh một số ví dụ từ mạng, đó là THAM GIA của tôi khiến tôi bối rối, nhưng tôi nghĩ rằng tôi đã nhận được nó ngay bây giờ.
stephmoreland

Sẽ tốt hơn nếu thực hiện các phép nối bên ngoài truy vấn con nếu không điều gì làm cho dữ liệu "khác biệt", vì để giảm thiểu dữ liệu bạn truy vấn và sao chép chỉ để "vứt bỏ" bằng cách chọn num = 1 từ chức năng cửa sổ.
Allan S. Hansen

4

Có một vài cách để làm điều này. Hai cái chính tôi sử dụng là biểu thức bảng chung và truy vấn phụ. Sử dụng CTE, truy vấn của bạn sẽ trông giống như thế này:

WITH theResultSet AS
(
    SELECT DISTINCT(column) AS col1 FROM some.table
)
SELECT whatever
  FROM more.data AS a
  JOIN theResultSet as b ON a.col1 = b.col1
  /* additional joins, clauses etc...*/

Hoặc sử dụng truy vấn con:

SELECT whatever
  FROM more.data AS a
  JOIN (SELECT DISTINCT(column) AS col1 FROM some.table) AS b ON a.col1 = b.col1
/* additional joins, clauses etc... */

Tôi thường kiểm tra xem cái nào nhanh hơn và đi với cái đó.

Tôi hy vọng cái này sẽ giúp bạn.


Tôi nghĩ rằng tôi đã hiểu câu trả lời của bạn nên tôi đã thử nó (câu đầu tiên), nhưng tôi nghĩ rằng THAM GIA của tôi đang gây ra vấn đề với THAM GIA giải pháp của bạn.
stephmoreland

cột cần phải khác biệt là gì? Tôi sẽ đăng một giải pháp toàn diện hơn cho bạn.
Mr.Brownstone


1

(Tôi nghĩ những gì bạn đang cố gắng làm là "thu gọn" từng hàng kết quả cho một sản phẩm, vì vậy câu trả lời này đang diễn ra với giả định đó.)

Điều này là không thể. Để lấy dữ liệu 1 .. * liên quan từ các bảng khác, bạn phải trả về các giá trị trùng lặp trong các cột khác.

Nói chung, cách để xử lý việc này là chạy truy vấn như hiện tại và xử lý tập kết quả đã tham gia trong mã ứng dụng. Tôi thường làm điều này bằng cách sử dụng phương pháp tiếp cận băm kết thúc với các thực thể riêng biệt của từng loại trong bộ sưu tập dựa trên một giá trị chính.

Mặc dù cách tiếp cận này tốn nhiều chi phí hơn về lưu lượng mạng, nhưng thông thường nên thực hiện một số việc như chạy nhiều truy vấn và ghép các kết quả khi bạn cần trong mã ứng dụng. Nó phụ thuộc vào nhiều yếu tố, bao gồm tần suất truy vấn / truy vấn chạy và lượng dữ liệu được trả về.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.