Truy vấn SQL đơn giản nhất để tìm giá trị lớn thứ hai là gì?


168

Truy vấn SQL đơn giản nhất để tìm giá trị nguyên lớn thứ hai trong một cột cụ thể là gì?

Có thể có các giá trị trùng lặp trong cột.


sử dụng offset cho mục đích này ... chọn tiện ích mở rộng từ [dbo]. [Nhân viên] đặt hàng theo phần mở rộng desc offset 2 hàng chỉ lấy 1 hàng tiếp theo
Jinto John

Câu trả lời:


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

7
Câu trả lời của Matt cũng như của Vinoy cũng quan tâm đến các bản sao. Giả sử giá trị lớn nhất được lặp lại sau đó sử dụng câu trả lời của Matt sẽ tạo ra giá trị lớn thứ hai chính xác trong khi nếu bạn sử dụng phương pháp 2 descmin hàng đầu , bạn có thể nhận được giá trị lớn nhất thay thế.
Pankaj Sharma

Điều gì sẽ xảy ra nếu có nhiều giây cao nhất ... Sau đó, điều này sẽ không cung cấp cho tất cả các Tuples
Parth Satra

2
cảm ơn bạn, đã sử dụng nó để tìm ngày cuối cùng thứ hai ở đây
shaijut

Nhiều hơn cách tiếp cận của tôi sử dụng ORDER_BY và LIMIT cho tuyên bố bên trong
andig

Lưu ý điều này sẽ không trả về kết quả nếu không có hồ sơ trước yêu cầu.
andig

61
SELECT MAX(col) FROM table WHERE col NOT IN (SELECT MAX(col) FROM table);

31

Trong T-Sql có hai cách:

--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 

Trong Microsoft SQL, cách thứ nhất nhanh gấp đôi so với cách thứ hai, ngay cả khi cột trong câu hỏi được phân cụm.

Điều này là do hoạt động sắp xếp tương đối chậm so với quét bảng hoặc chỉ mục mà maxtập hợp sử dụng.

Ngoài ra, trong Microsoft SQL 2005 trở lên, bạn có thể sử dụng ROW_NUMBER()chức năng:

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

20

Tôi thấy cả một số SQL Server cụ thể và một số giải pháp cụ thể của MySQL ở đây, vì vậy bạn có thể muốn làm rõ cơ sở dữ liệu nào bạn cần. Mặc dù nếu tôi phải đoán tôi sẽ nói SQL Server vì đây là chuyện nhỏ trong MySQL.

Tôi cũng thấy một số giải pháp sẽ không hiệu quả vì chúng không tính đến khả năng trùng lặp, vì vậy hãy cẩn thận với những giải pháp bạn chấp nhận. Cuối cùng, tôi thấy một số sẽ hoạt động nhưng điều đó sẽ thực hiện hai lần quét hoàn chỉnh của bảng. Bạn muốn chắc chắn rằng lần quét thứ 2 chỉ nhìn vào 2 giá trị.

Máy chủ SQL (trước năm 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

Cập nhật:

SQL Server 2012 hiện hỗ trợ cú pháp OFFSET / FETCH sạch hơn (và tiêu chuẩn ):

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

Đây là những gì tôi đã hy vọng nhìn thấy. Câu trả lời được chấp nhận trở nên xấu xí nếu bạn cần nó để làm việc cho bất kỳ n. Cái này đứng đó kiểm tra.
Robin Maben

@RobinMaben Robin, làm thế nào về kịch bản khi giá trị lớn nhất được lặp lại? Giả sử một cột chứa các số từ 1 đến 100 nhưng 100 được lặp lại hai lần. Sau đó, giải pháp này sẽ tạo ra giá trị lớn thứ hai là 100, sẽ không chính xác. Đúng?
Pankaj Sharma

1
@PankajSharma không, điều này vẫn sẽ hoạt động, vì mệnh đề GROUP BY
Joel Coehoorn

Đây là cách tiêu chuẩn để làm điều này. Câu trả lời được chấp nhận nên được cập nhật cho câu hỏi này.
Guilherme Melo

1
Tôi nhận được một lỗi cho biết tôi không thể sử dụng TOPOFFSETtrong cùng một truy vấn.
Giả mạo

15

Tôi cho rằng bạn có thể làm một cái gì đó như:

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

hoặc là

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

tùy thuộc vào máy chủ cơ sở dữ liệu của bạn. Gợi ý: Máy chủ SQL không làm GIỚI HẠN.


update- SQL Server 2012 đã thêm một mệnh đề offset / fetch tương tự như dbadiaries.com/
iliketocode

Giả sử bạn có 2 phần tử có cùng giá trị nhưng cũng là phần tử lớn nhất. Tôi đoán bạn phải làmOFFSET 2
Kangkan

Thêm mệnh đề GROUP BY sẽ phục vụ điều kiện trùng lặp trong phần này.
Saif

7

Cách dễ nhất là lấy giá trị thứ hai từ tập kết quả này trong ứng dụng:

SELECT DISTINCT value FROM Table ORDER BY value DESC LIMIT 2

Nhưng nếu bạn phải chọn giá trị thứ hai bằng SQL, thì:

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

1
Bạn đã chạy cái này trên SQL Server chưa?
Craig

1
@Craig - LIMITlà cú pháp MySql, câu hỏi không chỉ định phiên bản SQL.
Keith


4

Một truy vấn rất đơn giản để tìm giá trị lớn thứ hai

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

Không cần truy vấn phụ ... chỉ cần bỏ qua một hàng và chọn hàng thứ hai sau khi đặt hàng bằng cách giảm dần


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

Truy vấn này sẽ trả về mức lương tối đa, từ kết quả - không chứa mức lương tối đa từ bảng tổng thể.


2
Bạn có thể chỉnh sửa để giải thích làm thế nào điều này khác biệt đáng kể so với các câu trả lời cũ?
Nathan Tuggy

3

Câu hỏi cũ tôi biết, nhưng điều này đã cho tôi một kế hoạch thực hiện tốt hơn:

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

3

Đây là mã rất đơn giản, bạn có thể thử điều này: -

ví dụ: Tên bảng = kiểm tra

salary 

1000
1500
1450
7500

Mã MSSQL để có giá trị lớn thứ 2

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

ở đây 'offset 1 hàng' có nghĩa là hàng thứ 2 của bảng và 'chỉ tìm nạp 1 hàng tiếp theo' chỉ để hiển thị 1 hàng đó. nếu bạn không sử dụng 'chỉ tìm nạp 1 hàng tiếp theo' thì nó sẽ hiển thị tất cả các hàng từ hàng thứ hai.


Tối ưu hóa và tài nguyên thân thiện nhất Trả lời. Tôi đã tiết kiệm khá nhiều thời gian sử dụng nó trong truy vấn con của tôi. Cảm ơn.
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

Hy vọng điều này sẽ giúp có được giá trị cho bất kỳ hàng .....


2

Đơn giản nhất trong tất cả

select sal from salary order by sal desc limit 1 offset 1

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

Ghi chú

sal là tên col
emp là tên bảng


1

Tom, tin rằng điều này sẽ thất bại khi có nhiều hơn một giá trị được trả về trong select max([COLUMN_NAME]) from [TABLE_NAME]phần. tức là nơi có nhiều hơn 2 giá trị trong tập dữ liệu.

Sửa đổi nhẹ cho truy vấn của bạn sẽ hoạt động -

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));

truy vấn con trả về tất cả các giá trị khác với giá trị lớn nhất. chọn giá trị tối đa từ danh sách trả về.


1
select col_name
from (
    select dense_rank() over (order by col_name desc) as 'rank', col_name
    from table_name ) withrank 
where rank = 2

1
SELECT 
    * 
FROM 
    table 
WHERE 
    column < (SELECT max(columnq) FROM table) 
ORDER BY 
    column DESC LIMIT 1

1

Đó là cách tuyệt vời nhất:

SELECT
      Column name
FROM
      Table name 
ORDER BY 
      Column name DESC
LIMIT 1,1

1
select age from student group by id having age<(select max(age) from student)order by age limit 1

1

Như bạn đã đề cập các giá trị trùng lặp. Trong trường hợp như vậy, bạn có thể sử dụng DISTINCTGROUP BY để tìm ra giá trị cao thứ hai

Đây là một cái bàn

lương

:

nhập mô tả hình ảnh ở đây

NHÓM THEO

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

KHOẢNG CÁCH

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

Phần đầu tiên của LIMIT = chỉ mục bắt đầu

Phần thứ hai của LIMIT = có bao nhiêu giá trị


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

điều này sẽ trả lại mức lương cao thứ ba của bảng emp


1
select max(column_name) from table_name
where column_name not in (select max(column_name) from table_name);

không phải là một điều kiện loại trừ giá trị cao nhất của cột_name.

Tham khảo: phỏng vấn lập trình viên


0

Một cái gì đó như thế này? Tôi chưa thử nó, mặc dù:

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


0

Sử dụng truy vấn tương quan:

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)

Truy vấn này chọn ba mức lương tối đa. Nếu hai emp có cùng mức lương thì điều này không ảnh hưởng đến truy vấn.


0
select top 1 MyIntColumn from MyTable
where
 MyIntColumn <> (select top 1 MyIntColumn from MyTable order by MyIntColumn desc)
order by MyIntColumn desc

0

Điều này hoạt động trong MS SQL:

select max([COLUMN_NAME]) from [TABLE_NAME] where [COLUMN_NAME] < 
 ( select max([COLUMN_NAME]) from [TABLE_NAME] )
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.