วิธีการสั่งซื้อโดยสหภาพใน 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.