SQL Query ที่ง่ายที่สุดในการค้นหาค่าที่ใหญ่เป็นอันดับสองคืออะไร?


168

แบบสอบถาม SQL ที่ง่ายที่สุดในการค้นหาค่าจำนวนเต็มที่ใหญ่ที่สุดที่สองในคอลัมน์ที่ระบุคืออะไร?

อาจมีค่าซ้ำกันในคอลัมน์


ใช้อ็อฟเซ็ตสำหรับจุดประสงค์นี้ ... เลือกส่วนขยายจาก [dbo] [พนักงาน] สั่งซื้อโดยส่วนขยายเรียงจากมากไปน้อย 2 แถวเรียก 1 แถวถัดไปเท่านั้น
Jinto John

คำตอบ:


294
SELECT MAX( col )
  FROM table
 WHERE col < ( SELECT MAX( col )
                 FROM table )

7
คำตอบของ Matt และ Vinoy ก็ดูแลเรื่องที่ซ้ำซ้อนเช่นกัน สมมติว่ามีค่ามากที่สุดซ้ำแล้วใช้คำตอบของ Matt จะสร้างค่าที่ใหญ่เป็นอันดับสองที่ถูกต้องในขณะที่ถ้าคุณใช้วิธีการเรียงลำดับจากน้อยไปมากและต่ำสุด 2 อันดับคุณอาจได้รับค่ามากที่สุดแทน
Pankaj Sharma

เกิดอะไรขึ้นถ้ามีหลายวินาทีที่สูงที่สุด ... แล้วนี่จะไม่ให้ Tuples ทั้งหมด
Parth Satra

2
ขอขอบคุณใช้สิ่งนี้เพื่อหาวันที่
shaijut

ดีกว่าวิธีของฉันโดยใช้ ORDER_BY และ LIMIT สำหรับคำสั่งภายใน
andig

โปรดทราบว่านี่จะไม่ส่งคืนผลลัพธ์หากไม่มีระเบียนก่อนที่จะมีการร้องขอ
andig


31

ใน T-Sql มีสองวิธี:

--filter out the max
select max( col )
from [table]
where col < ( 
    select max( col )
    from [table] )

--sort top two then bottom one
select top 1 col 
from (
    select top 2 col 
    from [table]
    order by col) topTwo
order by col desc 

ใน Microsoft SQL วิธีแรกนั้นเร็วเป็นสองเท่าของอันดับที่สองแม้ว่าคอลัมน์ที่เป็นปัญหาจะถูกทำคลัสเตอร์

นี่เป็นเพราะการดำเนินการเรียงลำดับค่อนข้างช้าเมื่อเทียบกับการสแกนตารางหรือดัชนีที่ maxรวมใช้

อีกทางเลือกหนึ่งใน Microsoft SQL 2005 และสูงกว่าคุณสามารถใช้ROW_NUMBER()ฟังก์ชัน:

select col
from (
    select ROW_NUMBER() over (order by col asc) as 'rowNum', col
    from [table] ) withRowNum 
where rowNum = 2

20

ฉันเห็นทั้ง SQL Server เฉพาะและโซลูชัน MySQL บางตัวที่นี่ดังนั้นคุณอาจต้องการชี้แจงฐานข้อมูลที่คุณต้องการ แม้ว่าฉันต้องเดาฉันจะพูดว่า SQL Server เพราะนี่เป็นเรื่องเล็กน้อยใน MySQL

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

SQL Server (ก่อนปี 2012):

SELECT MIN([column]) AS [column]
FROM (
    SELECT TOP 2 [column] 
    FROM [Table] 
    GROUP BY [column] 
    ORDER BY [column] DESC
) a

MySQL:

SELECT `column` 
FROM `table` 
GROUP BY `column` 
ORDER BY `column` DESC 
LIMIT 1,1

ปรับปรุง:

SQL Server 2012 ในขณะนี้สนับสนุนการทำความสะอาดมาก (และมาตรฐาน ) OFFSET / เรียกไวยากรณ์:

SELECT TOP 2 [column] 
FROM [Table] 
GROUP BY [column] 
ORDER BY [column] DESC
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY;

นี่คือสิ่งที่ฉันหวังว่าจะได้เห็น nคำตอบที่ได้รับการยอมรับจะเปิดน่าเกลียดถ้าคุณจำเป็นต้องใช้มันในการทำงานสำหรับการใด ๆ อันนี้ย่อมาจากการทดสอบที่
Robin Maben

@ RobinMaben Robin แล้วสถานการณ์จะเกิดขึ้นซ้ำอีกครั้งเมื่อไร สมมติว่าคอลัมน์มีตัวเลข 1 ถึง 100 แต่ 100 ซ้ำสองครั้ง จากนั้นโซลูชันนี้จะสร้างมูลค่าที่ใหญ่ที่สุดที่สองเป็น 100 ซึ่งจะไม่ถูกต้อง ขวา?
Pankaj Sharma

1
@PankajSharma ไม่สิ่งนี้จะยังคงใช้งานได้เนื่องจากข้อ GROUP BY
Joel Coehoorn

นี่เป็นวิธีมาตรฐานในการทำเช่นนี้ คำตอบที่ยอมรับควรได้รับการอัปเดตเป็นคำตอบนี้
Guilherme Melo

1
ฉันได้รับข้อผิดพลาดซึ่งแจ้งว่าฉันไม่สามารถใช้TOPและOFFSETอยู่ในแบบสอบถามเดียวกันได้
เก๊

15

ฉันคิดว่าคุณสามารถทำสิ่งที่ชอบ:

SELECT * FROM Table ORDER BY NumericalColumn DESC LIMIT 1 OFFSET 1

หรือ

SELECT * FROM Table ORDER BY NumericalColumn DESC LIMIT (1, 1)

ขึ้นอยู่กับเซิร์ฟเวอร์ฐานข้อมูลของคุณ คำแนะนำ: SQL Server ไม่ได้ทำการ จำกัด


update- SQL Server 2012 เพิ่มส่วน offset / fetch คล้ายกับdbadiaries.com/
iliketocode

สมมติว่าคุณมี 2 องค์ประกอบที่มีค่าเท่ากัน แต่ก็เป็นองค์ประกอบที่ใหญ่ที่สุด ฉันเดาว่าคุณต้องทำOFFSET 2
คัง

การเพิ่ม GROUP BY clause จะให้เงื่อนไขที่ซ้ำกันในสิ่งนี้
Saif

7

วิธีที่ง่ายที่สุดคือการรับค่าที่สองจากชุดผลลัพธ์นี้ในแอปพลิเคชัน:

SELECT DISTINCT value FROM Table ORDER BY value DESC LIMIT 2

แต่ถ้าคุณต้องเลือกค่าที่สองโดยใช้ SQL จะทำอย่างไร:

SELECT MIN(value) FROM (SELECT DISTINCT value FROM Table ORDER BY value DESC LIMIT 2) AS t

1
คุณรันสิ่งนี้บน SQL Server หรือไม่
เครก

1
@Craig - LIMITเป็นไวยากรณ์ MySql คำถามไม่ได้ระบุเวอร์ชัน SQL
Keith

7

คุณสามารถค้นหาคอลัมน์ที่มีค่ามากที่สุดเป็นอันดับสองโดยใช้แบบสอบถามต่อไปนี้

SELECT *
FROM TableName a
WHERE
  2 = (SELECT count(DISTINCT(b.ColumnName))
       FROM TableName b WHERE
       a.ColumnName <= b.ColumnName);

คุณสามารถค้นหารายละเอียดเพิ่มเติมได้ที่ลิงค์ต่อไปนี้

http://www.abhishekbpatel.com/2012/12/how-to-get-nth-maximum-and-minimun.html


ที่เก็บถาวรของลิงค์ตาย: web.archive.org/web/20130406161645/http://…
xgMz

4

คำค้นหาที่ง่ายมากในการค้นหาค่าที่ใหญ่เป็นอันดับสอง

SELECT `Column` FROM `Table` ORDER BY `Column` DESC LIMIT 1,1;

4

MSSQL

SELECT  *
  FROM [Users]
    order by UserId desc OFFSET 1 ROW 
FETCH NEXT 1 ROW ONLY;

MySQL

SELECT  *
  FROM Users
    order by UserId desc LIMIT 1 OFFSET 1

ไม่จำเป็นต้องมีคิวรีย่อย ... เพียงข้ามหนึ่งแถวแล้วเลือกแถวที่สองหลังจากสั่งซื้อจากมากไปน้อย


3
SELECT MAX(Salary) FROM Employee WHERE Salary NOT IN (SELECT MAX(Salary) FROM Employee )

แบบสอบถามนี้จะส่งคืนเงินเดือนสูงสุดจากผลลัพธ์ - ซึ่งไม่มีเงินเดือนสูงสุดจากตารางโดยรวม


2
คุณสามารถแก้ไขเพื่ออธิบายว่าสิ่งนี้แตกต่างอย่างมากจากคำตอบเดิมหรือไม่
นาธาน Tuggy

3

คำถามเก่า ๆ ที่ฉันรู้ แต่สิ่งนี้ทำให้ฉันมีแผนปฏิบัติการที่ดีกว่า:

 SELECT TOP 1 LEAD(MAX (column)) OVER (ORDER BY column desc)
 FROM TABLE 
 GROUP BY column

3

นี่คือรหัสที่ง่ายมากคุณสามารถลอง: -

ตัวอย่าง: ชื่อตาราง = ทดสอบ

salary 

1000
1500
1450
7500

รหัส MSSQL เพื่อรับค่าที่ใหญ่เป็นอันดับสอง

select salary from test order by salary desc offset 1 rows fetch next 1 rows only;

ที่นี่ 'ชดเชย 1 แถว' หมายถึงแถวที่ 2 ของตารางและ 'ดึงข้อมูล 1 แถวถัดไปเท่านั้น' สำหรับแสดงเพียง 1 แถว หากคุณไม่ใช้ 'ดึงข้อมูล 1 แถวถัดไปเท่านั้น' จะแสดงแถวทั้งหมดจากแถวที่สอง


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

2

select * from (select ROW_NUMBER() over (Order by Col_x desc) as Row, Col_1
    from table_1)as table_new tn inner join table_1 t1
    on tn.col_1 = t1.col_1
where row = 2

หวังว่าความช่วยเหลือนี้จะได้รับความคุ้มค่าสำหรับแถวใด ๆ .....



1
select min(sal) from emp where sal in 
    (select TOP 2 (sal) from emp order by sal desc)

บันทึก

sal เป็นชื่อ col
emp คือชื่อตาราง


1

ทอมเชื่อว่าสิ่งนี้จะล้มเหลวเมื่อมีการคืนค่ามากกว่าหนึ่งค่า select max([COLUMN_NAME]) from [TABLE_NAME]ส่วน เช่นที่มีมากกว่า 2 ค่าในชุดข้อมูล

การปรับเปลี่ยนเล็กน้อยในแบบสอบถามของคุณจะทำงาน -

select max([COLUMN_NAME]) from [TABLE_NAME] where [COLUMN_NAME] **IN** 
  ( select max([COLUMN_NAME]) from [TABLE_NAME] )

1
select max(COL_NAME) from TABLE_NAME where COL_NAME in 
    (select COL_NAME from TABLE_NAME where COL_NAME < (select max(COL_NAME) from TABLE_NAME));

แบบสอบถามย่อยส่งกลับค่าทั้งหมดนอกเหนือจากที่ใหญ่ที่สุด เลือกค่าสูงสุดจากรายการที่ส่งคืน






1

ตามที่คุณกล่าวถึงค่าที่ซ้ำกัน ในกรณีเช่นนี้คุณอาจใช้DISTINCTและGROUP BYเพื่อค้นหาค่าสูงสุดอันดับสอง

นี่คือตาราง

เงินเดือน

:

ป้อนคำอธิบายรูปภาพที่นี่

จัดกลุ่มตาม

SELECT  amount FROM  salary 
GROUP by amount
ORDER BY  amount DESC 
LIMIT 1 , 1

ที่แตกต่าง

SELECT DISTINCT amount
FROM  salary 
ORDER BY  amount DESC 
LIMIT 1 , 1

ส่วนแรกของ LIMIT = ดัชนีเริ่มต้น

ส่วนที่สองของ LIMIT = จำนวนเท่าใด


1
SELECT MAX(sal) FROM emp
WHERE sal NOT IN (SELECT top 3 sal FROM emp order by sal desc )

นี่จะส่งคืนตาราง sal ที่สูงที่สุดเป็นอันดับสาม



0

อะไรแบบนี้? ฉันยังไม่ได้ทดสอบ แต่:

select top 1 x
from (
  select top 2 distinct x 
  from y 
  order by x desc
) z
order by x


0

การใช้คิวรีที่สัมพันธ์กัน:

Select * from x x1 where 1 = (select count(*) from x where x1.a < a)

0
select * from emp e where 3>=(select count(distinct salary)
    from emp where s.salary<=salary)

แบบสอบถามนี้เลือกเงินเดือนสูงสุดสามรายการ หากพนักงานสองคนได้รับเงินเดือนเท่ากันสิ่งนี้จะไม่ส่งผลต่อการสืบค้น



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