เลือก DISTINCT ในหนึ่งคอลัมน์ขณะส่งคืนคอลัมน์อื่นหรือไม่


12

ฉันมีแบบสอบถามซึ่งใช้ตารางการค้นหาสามตารางเพื่อรับข้อมูลทั้งหมดที่ฉันต้องการ ฉันต้องมีDISTINCTค่าสำหรับหนึ่งคอลัมน์ แต่ฉันต้องการข้อมูลที่เหลือที่เกี่ยวข้องอีกด้วย

รหัส SQL ของฉัน:

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;

ฉันต้องการรับผลิตภัณฑ์ทั้งหมดจากแบบสอบถามนี้ แต่ฉันต้องการรับเพียงครั้งเดียวเพราะฉันมีเมนูแบบเลื่อนลงสำหรับแอปพลิเคชันการค้นหา ฉันต้องการให้ผู้ใช้สามารถเลือกผลิตภัณฑ์ที่อยู่ในตารางนั้นได้ (นั่นเป็นสาเหตุที่ฉันต้องการเพียงครั้งเดียวเท่านั้น)

มันซับซ้อนเกินไปหรือเปล่า ฉันควรใช้วิธีที่ง่ายกว่านี้หรือไม่?


แต่ผลิตภัณฑ์เกี่ยวข้องกับเอกสารจำนวนมาก และแบบสอบถามของคุณจะส่งคืนทั้งหมด (เอกสารสำหรับผลิตภัณฑ์) ควรเลือกอันไหน
ypercubeᵀᴹ

คำตอบ:


7

อีกวิธีที่ยังไม่ได้กล่าวถึงคือการใช้ฟังก์ชั่นหน้าต่างเช่น 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- ขอบคุณ! ที่ได้ผล ทุกครั้งที่ฉันพยายามที่จะปรับตัวอย่างจากเน็ตมันเป็น JOINS ของฉันที่ทำให้ฉันสับสน แต่ฉันคิดว่าตอนนี้ฉันเข้าใจแล้ว
stephmoreland

จะเป็นการดีกว่าถ้าทำการรวมนอกแบบสอบถามย่อยหากไม่ใช่สิ่งที่ทำให้ข้อมูล "แตกต่าง" เพื่อลดข้อมูลที่คุณค้นหาและทำซ้ำเพื่อ "ทิ้ง" โดยการเลือก num = 1 จากฟังก์ชันหน้าต่าง
อัลลันเอส. แฮนเซน

4

มีสองสามวิธีในการทำเช่นนี้ สองหลักที่ฉันใช้เป็นนิพจน์ตารางทั่วไปและแบบสอบถามย่อย การใช้ CTE ข้อความค้นหาของคุณจะเป็นดังนี้:

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...*/

หรือใช้แบบสอบถามย่อย:

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... */

ปกติฉันจะทดสอบเพื่อดูว่าเร็วกว่าและไปกับอันนั้น

ฉันหวังว่านี่จะช่วยคุณได้


ฉันคิดว่าฉันเข้าใจคำตอบของคุณดังนั้นฉันจึงลอง (อันแรก) แต่ฉันคิดว่าข้อต่อของฉันทำให้เกิดปัญหากับการเข้าร่วมโซลูชันของคุณ
stephmoreland

คอลัมน์ที่ต้องระบุคืออะไร ฉันจะโพสต์โซลูชั่นที่ครอบคลุมมากขึ้นสำหรับคุณ
Mr.Brownstone

product.displayheading เป็นคอลัมน์
stephmoreland

1

(ฉันคิดว่าสิ่งที่คุณพยายามจะทำคือ "ยุบ" แต่ละแถวผลลัพธ์ไปยังผลิตภัณฑ์เดียวดังนั้นคำตอบนี้จะเกิดขึ้นตามสมมติฐานนั้น)

สิ่งนี้เป็นไปไม่ได้ ในการรับข้อมูล 1 .. * ที่เกี่ยวข้องจากตารางอื่นคุณต้องส่งคืนค่าที่ซ้ำกันในคอลัมน์อื่น

โดยทั่วไปวิธีการจัดการสิ่งนี้คือการเรียกใช้แบบสอบถามตามที่เป็นอยู่และประมวลผลชุดผลลัพธ์ในรหัสแอปพลิเคชัน ฉันมักจะทำเช่นนี้โดยใช้วิธีการรวบรวมแฮชที่ลงท้ายด้วยเอนทิตีที่แตกต่างกันของแต่ละประเภทในการรวบรวมตามค่าคีย์

ในขณะที่วิธีการนี้มีค่าใช้จ่ายมากขึ้นในแง่ของการรับส่งข้อมูลเครือข่าย แต่โดยทั่วไปแล้วการทำบางอย่างเช่นการเรียกใช้หลาย ๆ แบบสอบถามและการประสานผลลัพธ์ตามที่คุณต้องการในรหัสแอปพลิเคชัน ขึ้นอยู่กับปัจจัยหลายประการรวมถึงความถี่ในการเรียกใช้คิวรี / คิวรีและข้อมูลที่ส่งคืน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.