วิธีการสั่งซื้อโดยสหภาพใน SQL?


201

เป็นไปได้หรือไม่ที่จะเรียงลำดับเมื่อข้อมูลมาจากตัวเลือกมากมายและรวมเข้าด้วยกัน? เช่น

Select id,name,age
From Student
Where age < 15
Union
Select id,name,age
From Student
Where Name like "%a%"

ฉันจะสั่งเคียวรีนี้ด้วยชื่อได้อย่างไร

บางคนบอกว่าคุณสามารถสืบค้นแบบนี้

Select id,name,age
From Student
Where age < 15 or name like "%a%"
Order by name

แต่ในกรณีนี้ฉันไม่สนใจโซลูชันนั้น


1
หากคุณมีคอลัมน์เดียวกันในแบบสอบถามแบบร่วมเมื่อสิ้นสุดการสั่งซื้อด้วยชื่อคอลัมน์ของคุณ
anirban karak

คำตอบ:


266

แค่เขียน

Select id,name,age
From Student
Where age < 15
Union
Select id,name,age
From Student
Where Name like "%a%"
Order by name

คำสั่งซื้อโดยใช้กับชุดผลลัพธ์ทั้งหมด


45
จะเป็นอย่างไรถ้าฉันต้องการให้การเรียงลำดับใช้กับอันดับสูงสุดของ UNION เท่านั้น
marifrahman

7
@marifrahman ดูคำตอบของฉันstackoverflow.com/a/43855496/2340825
BA TabNabber

2
@marifrahman ขออภัยที่ขุดหัวข้อเก่า แต่อาจช่วยคนอื่นได้ ในกรณีที่คุณต้องการให้ ORDER BY นำไปใช้กับส่วนแรกของ UNION ให้ปกป้อง SELECT นี้ด้วยเครื่องหมายวงเล็บ
Lideln Kyoku

82
Select id,name,age
from
(
   Select id,name,age
   From Student
   Where age < 15
  Union
   Select id,name,age
   From Student
   Where Name like "%a%"
) results
order by name

46
ตามที่นิยามไว้ bernd_k แต่ละคำสั่ง SELECT ที่ประกอบขึ้นเป็น UNION ไม่ได้รับอนุญาตให้มีคำสั่งย่อย ORDER BY คำสั่ง ORDER เดียวเท่านั้นที่อนุญาตให้ใช้ได้ในตอนท้ายของ UNION และใช้กับสหภาพทั้งหมดทำให้xxx UNION yyy ORDER BY zzzeqivalent ของ(xxx UNION yyy) ORDER BY zzz
Nicholas Carey

39

เพื่อที่จะทำให้การเรียงลำดับใช้กับคำสั่งแรกใน UNION เท่านั้นคุณสามารถใส่มันลงในการเลือกย่อยด้วย UNION ALL (ทั้งสองสิ่งนี้ดูเหมือนจะจำเป็นใน Oracle):

Select id,name,age FROM 
(    
 Select id,name,age
 From Student
 Where age < 15
 Order by name
)
UNION ALL
Select id,name,age
From Student
Where Name like "%a%"

หรือ (ตามความคิดเห็นของ Nicholas Carey) คุณสามารถรับประกันการเลือกอันดับสูงสุดและผลลัพธ์จะปรากฏอยู่ด้านบน SELECT ด้านล่างดังนี้:

Select id,name,age, 1 as rowOrder
From Student
Where age < 15
UNION
Select id,name,age, 2 as rowOrder
From Student
Where Name like "%a%"
Order by rowOrder, name

4
ใช่. นั่นสั่งผลของการเลือกย่อย ที่ไม่ได้เรียงลำดับผลลัพธ์ของselectคำสั่งที่อ้างถึงการเลือกย่อย ตามมาตรฐาน SQL ลำดับของผลลัพธ์จะไม่ได้กำหนดยกเว้นorder byข้อที่ชัดเจน สิ่งแรกselectในตัวอย่างของคุณอาจส่งคืนผลลัพธ์ในลำดับที่ส่งกลับโดยการเลือกย่อย แต่ไม่รับประกัน ยิ่งไปกว่านั้นนั่นคือ* ไม่ *รับประกันการสั่งซื้อชุดผลลัพธ์ของทั้งหมดunion(กฎเดียวกันในมาตรฐาน) หากคุณขึ้นอยู่กับคำสั่งซื้อคุณจะถูกกัดในที่สุด
Nicholas Carey

1
@Nicholas Carey - เมื่อฉันเริ่มต้นทดสอบโดยใช้ UNION มันมีพฤติกรรมที่คาดเดาไม่ได้ตามที่คุณอธิบายฉันคิดว่า UNION ALL (อย่างน้อยใน Oracle) จำเป็นต้องสั่งซื้อ SELECT ระดับบนสุดด้านล่าง อย่างไรก็ตามฉันได้เตรียมทางเลือกที่รับประกันการสั่งซื้อที่ถูกต้องและควรเป็นฐานข้อมูลที่เป็นอิสระ
BA TabNabber

ไม่ทำงานสำหรับฉัน SELECTหนึ่งที่มียูเนี่ยนทั้งหมดยังคงล้มเหลวในการรักษาความสงบเรียบร้อยภายในครั้งแรก
Amit Chigadani

และปัญหาของแบบสอบถามที่สองคือมันไม่ได้กำจัดระเบียนที่ซ้ำกัน เนื่องจากคุณได้เพิ่มคอลัมน์ 'rowOrder' อีกคอลัมน์หนึ่งซึ่งอาจมีค่าแตกต่างจากระเบียนที่ซ้ำกัน วัตถุประสงค์ของสหภาพกับสหภาพทั้งหมดจะหายไป
Amit Chigadani

1
@AmitChigadani การกำจัดรายการที่ซ้ำกันไม่ได้เป็นส่วนหนึ่งของคำถามเดิม แต่ต้องทำเช่นนั้นคำสั่ง WHERE สามารถแก้ไขได้เพื่อให้แน่ใจว่ามีความเป็นเอกลักษณ์ เช่น: โดยที่ชื่อเช่น "% a%" AND age> = 15
BA TabNabber

12

ทั้งคำตอบอื่น ๆ นั้นถูกต้อง แต่ฉันคิดว่ามันคุ้มค่าที่จะสังเกตว่าสถานที่ที่ฉันติดอยู่นั้นไม่ได้ตระหนักว่าคุณจะต้องสั่งซื้อโดยนามแฝงและตรวจสอบให้แน่ใจว่านามแฝงนั้นเหมือนกันสำหรับทั้งสองตัวเลือก ... ดังนั้น

select 'foo'
union
select item as `foo`
from myTable
order by `foo`

สังเกตเห็นว่าฉันกำลังใช้เครื่องหมายคำพูดเดี่ยวในตัวเลือกแรก แต่ให้ใส่เครื่องหมายอื่น ๆ

ที่จะให้คุณเรียงลำดับที่คุณต้องการ


อะไรคือสิ่งสำคัญที่คุณต้องการใช้ในการใช้เครื่องหมายคำพูดเดี่ยวในตัวเลือกแรกและ backticks อื่น ๆ เป็นการดีที่ควรจะสอดคล้อง
nanosoft

ตัวเลือกแรกคือตัวอักษร มันเป็นหัวข้อเช่น 'NAMES' ตัวเลือกที่สองเป็นการอ้างอิงไปยังตาราง ดังนั้นแถวแรกของคุณจะพูดว่า "ชื่อ" และส่วนที่เหลือของแถวจะเป็นชื่อจริงที่เลือกจากตาราง ประเด็นก็คือส่วนหัวของคุณอาจเป็นสตริงเดียวกับชื่อของคอลัมน์ที่คุณกำลังเลือกและนี่เป็นวิธีการแก้ปัญหาสำหรับการใช้ป้ายกำกับที่คุณต้องการโดยไม่เกิดการชนกันในสหภาพของคุณ
Yevgeny Simkin

2
หลังจากการทดลองบางอย่างฉันเห็นว่านามแฝงที่กล่าวถึงในข้อ ORDER BY ต้องถูกกล่าวถึงในส่วนคำสั่ง SELECT คุณไม่สามารถจัดเรียงตามคอลัมน์อื่น แน่นอนว่าคุณสามารถSELECT a, b, c FROM (<insert union query here>) AS x;หลีกเลี่ยงสิ่งนั้นได้โดยการรวมทั้งหมดไว้ใน a หากคุณต้องการหลีกเลี่ยงการส่งคืนคอลัมน์พิเศษ
Wodin

11

Order Byถูกนำไปใช้หลังจากunionดังนั้นเพียงเพิ่มorder byส่วนท้ายของคำสั่ง:

Select id,name,age
From Student
Where age < 15
Union
Select id,name,age
From Student
Where Name like '%a%'
Order By name

9

ถ้าฉันต้องการให้การเรียงลำดับถูกนำไปใช้กับหนึ่งใน UNION หากใช้ Union all:

Select id,name,age
From Student
Where age < 15
Union all
Select id,name,age
From 
(
Select id,name,age
From Student
Where Name like "%a%"
Order by name
)

8

ตามคำตอบอื่น ๆ ที่ระบุไว้ 'สั่งซื้อโดย' หลังจาก LAST Union ควรใช้กับทั้งชุดข้อมูลที่เข้าร่วมโดยสหภาพ

ฉันมีชุดข้อมูลสองชุด แต่ใช้ตารางที่ต่างกัน แต่มีคอลัมน์เดียวกัน 'สั่งซื้อโดย' หลังจาก LAST Union ยังไม่ทำงาน การใช้ ALIAS สำหรับคอลัมน์ที่ใช้ใน 'เรียงตาม' ทำให้เกิดกลอุบาย

Select Name, Address for Employee 
Union
Select Customer_Name, Address from Customer
order by customer_name;   --Won't work

ดังนั้นการแก้ปัญหาคือใช้นามแฝง 'ชื่อผู้ใช้':

Select Name as User_Name, Address for Employee 
Union
Select Customer_Name as User_Name, Address from Customer
order by User_Name; 

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