ฉันเห็นคนจำนวนมากใช้คิวรีย่อยหรือคุณสมบัติเฉพาะของผู้จำหน่ายเพื่อทำสิ่งนี้ แต่ฉันมักจะทำคิวรีประเภทนี้โดยไม่มีคิวรีย่อยในวิธีต่อไปนี้ มันใช้ธรรมดา SQL มาตรฐานดังนั้นมันควรจะทำงานในทุกยี่ห้อของ RDBMS
SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
WHERE t2.UserId IS NULL;
กล่าวอีกนัยหนึ่ง: ดึงแถวจากt1ที่ไม่มีแถวอื่นที่มีวันเดียวกันUserIdและวันที่มากกว่า
(ฉันใส่ตัวระบุ "วันที่" ในตัวคั่นเพราะเป็นคำที่สงวนไว้ของ SQL)
ในกรณีที่t1."Date" = t2."Date"ปรากฏเป็นสองเท่า มักจะมีตารางที่สำคัญเช่นauto_inc(seq) idเพื่อหลีกเลี่ยงการเสแสร้งสามารถใช้ได้ดังนี้:
SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
ON t1.UserId = t2.UserId AND ((t1."Date" < t2."Date")
OR (t1."Date" = t2."Date" AND t1.id < t2.id))
WHERE t2.UserId IS NULL;
ความคิดเห็นอีกครั้งจาก @Farhan:
นี่คือคำอธิบายโดยละเอียดเพิ่มเติม:
การเข้าร่วม outer ความพยายามในการที่จะเข้าร่วมกับt1 t2ตามค่าเริ่มต้นผลลัพธ์ทั้งหมดt1จะถูกส่งคืนและหากมีการจับคู่ที่ตรงกันผลลัพธ์t2ก็จะถูกส่งคืนเช่นกัน หากไม่มีการจับคู่ในt2แถวที่ระบุt1แสดงว่าแบบสอบถามยังคงส่งคืนแถวt1และใช้NULLเป็นตัวยึดตำแหน่งสำหรับt2คอลัมน์ทั้งหมดของ นั่นเป็นเพียงวิธีที่การรวมภายนอกทำงานโดยทั่วไป
เคล็ดลับในแบบสอบถามนี้คือการออกแบบเข้าร่วมสภาพจับคู่ดังกล่าวว่าt2จะต้องตรงกับที่เหมือนกัน useridและมากขึ้น dateคิดถูกถ้าแถวมีอยู่ในt2ที่มีมากขึ้นdateแล้วแถวในt1มันเทียบกับการไม่สามารถเป็นคนที่ยิ่งใหญ่ที่สุดสำหรับการที่date useridแต่ถ้าไม่มีการแข่งขัน - คือถ้าไม่มีแถวที่มีอยู่ในt2ที่มีมากขึ้นdateกว่าแถวในt1- เรารู้ว่าแถวในt1เป็นแถวที่มีที่ยิ่งใหญ่ที่สุดสำหรับการที่ได้รับdateuserid
ในกรณีเหล่านั้น (เมื่อไม่มีการจับคู่) คอลัมน์ของt2จะเป็นNULL- แม้แต่คอลัมน์ที่ระบุในเงื่อนไขการเข้าร่วม เพื่อที่ว่าทำไมเราใช้WHERE t2.UserId IS NULLเพราะเรากำลังค้นหาสำหรับกรณีที่ไม่มีแถวก็พบว่ามีมากขึ้นสำหรับการที่ได้รับdateuserid