Làm thế nào để chỉ chọn 1 hàng từ oracle sql?


110

Tôi muốn sử dụng cú pháp oracle để chỉ chọn 1 hàng từ bảng DUAL. Ví dụ: tôi muốn thực hiện truy vấn này:

SELECT user 
  FROM DUAL

... và nó sẽ có, giống như, 40 bản ghi. Nhưng tôi chỉ cần một bản ghi. ... VÀ, tôi muốn làm cho nó xảy ra mà không cần một WHEREmệnh đề.

Tôi cần một cái gì đó trong trường tên_bảng chẳng hạn như:

SELECT FirstRow(user) 
  FROM DUAL

1
Phiên bản nào của Oracle? Sử dụng ROWNUM hoặc ROW_NUMBER (9i +) có nghĩa là cần mệnh đề WHERE
OMG Ponies

1
Bạn đã đặt tên cho một bảng dual?
ypercubeᵀᴹ

1
@ypercube duallà bảng hệ thống trong oracle

4
@Ben, bạn thực sự không nên tạo một bảng có tên DUAL. Nó hơi giống #define TRUE 0trong C - chắc chắn, nó có thể phù hợp với bạn, nhưng các nhà phát triển tương lai sẽ ghét bạn.
Jeffrey Kemp,

3
Bạn đã thực sự cố gắng chạy select user from dualchưa? Nếu không, hãy thử nó, và xem những gì bạn nhận được. Trên hệ thống oracle tiêu chuẩn, bạn sẽ lấy lại người dùng mà bạn đang thực hiện lệnh.
Shannon thôi việc vào

Câu trả lời:


169

Bạn sử dụng ROWNUM.

I E.

SELECT user FROM Dual WHERE ROWNUM = 1

http://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns009.htm


@ypercube xa như tôi có thể nói, nó có. (Ít nhất nó hoạt động để cài đặt của tôi về Oracle10g.)

@bdares: nó sẽ hoạt động, có. Nhưng không phải câu trả lời của bạn, với order by.
ypercubeᵀᴹ

1
Đúng. ROWNUM là một cột đặc biệt được thêm vào tập kết quả liệt kê các kết quả. Bạn có thể sử dụng nó để chọn nhiều là tốt, ví dụ, nếu bạn muốn tìm 10 nhân viên payed cao nhất, bạn có thể nói "người dùng chọn từ nhân viên ĐÂU ROWNUM <= 10 ORDER BY LƯƠNG giảm dần"
mindvirus

10
@mkdess: Không, ORDER BYđược áp dụng sau WHERE.
ypercubeᵀᴹ

15
Bạn cần:SELECT * FROM (SELECT user FROM Employees ORDER BY SALARY DESC) WHERE ROWNUM <= 10
ypercubeᵀᴹ

49

Tôi tìm thấy "giải pháp" này ẩn trong một trong các bình luận. Vì tôi đã tìm kiếm nó một lúc, tôi muốn làm nổi bật nó một chút (chưa thể nhận xét hoặc làm những thứ như vậy ...), vì vậy đây là những gì tôi đã sử dụng:

SELECT * FROM (SELECT [Column] FROM [Table] ORDER BY [Date] DESC) WHERE ROWNUM = 1

Thao tác này sẽ in cho tôi mục nhập [Cột] mong muốn từ mục nhập mới nhất trong bảng, giả sử rằng [Ngày] luôn được chèn qua SYSDATE.


Tôi thấy nó cũng sẽ hoạt động nếu bạn đặt hàng trước ROWID, miễn là bạn không bao giờ xóa bất kỳ bản ghi nào và luôn quan tâm đến bản ghi được chèn / sửa đổi cuối cùng.
vapcguy

@vapcguy: Đừng mong đợi ROWID được đặt hàng, ngay cả khi bạn không bao giờ xóa một hàng khỏi bảng! Ngay cả khi nó hoạt động cho bạn bây giờ, nó không bao giờ được đảm bảo sẽ hoạt động trong các phiên bản sau này.
D. Mika

@ D.Mika Trên thực tế, nếu nó hoạt động ngay bây giờ và bạn không bao giờ thêm / bớt / cập nhật / xóa các bản ghi, thì sẽ không bao giờ có vấn đề gì. Các bản ghi chỉ có thể được thay đổi nếu bạn thực sự thay đổi chúng. Có một quan niệm sai lầm này bằng cách nào đó ROWIDđược sửa đổi ngẫu nhiên bởi Oracle. Nó không phải. Nó dựa trên việc thực sự sửa đổi các hàng, tức là bạn xóa một hàng, sau đó chèn một hàng. Cái được chèn vào sẽ nhận được cái cũ ROWID. Có những thứ như bảng tĩnh không bao giờ có được trạng thái giống như cập nhật ở Hoa Kỳ là một ví dụ điển hình - nếu nó thay đổi, nó có thể sẽ có những hậu quả khác, dù sao, khi điều này là tốt.
vapcguy

@vapcguy: Chà, điều đó gần đúng. Nhưng có những hoạt động khác sẽ thay đổi ROWID. Điều gì sẽ xảy ra nếu bạn xuất / nhập bảng vì lý do nào đó? Có những hoạt động khác, nhưng một số trong số chúng cần BẬT DI CHUYỂN ROW. Tôi chỉ muốn nói rằng không nên dựa vào một chi tiết triển khai có thể thay đổi trong tương lai.
D. Mika

@ D.Mika Tôi chắc rằng nếu có bất kỳ thao tác nào ROWIDcó thể được thay đổi, một DBA giỏi sẽ tìm kiếm chúng và làm những gì có thể để tránh chúng nếu có khả năng chúng ảnh hưởng đến một bảng tĩnh như tôi đã mô tả. chỉ ứng dụng sẽ được hoạt động. SELECTThay vào đó, xuất bảng có thể được thực hiện bằng một câu lệnh. Việc nhập sẽ diễn ra một lần và sau đó không bao giờ nữa. Tôi hiểu ý bạn, chắc chắn cần phải cẩn thận, nhưng những vấn đề còn lâu mới có thể tránh khỏi.
vapcguy

35

Cú pháp này có sẵn trong Oracle 12c:

select * from some_table fetch first 1 row only;
select * from some_table fetch first 1 rows only;
select * from some_table fetch first 10 row only;
select * from some_table fetch first 10 rows only;

^^ Tôi chỉ muốn chứng minh rằng hàng hoặc hàng (số nhiều) đều có thể được sử dụng bất kể số lượng hàng mong muốn là bao nhiêu.)


1
chọn * từ some_table chỉ tìm nạp 1 hàng đầu tiên; nó không hoạt động trong swl devloper của tôi cũng như trong sql cộng với lỗi khi tìm nạp.
nikhil sugandh

Bạn đang sử dụng oracle 12c?
mancini0

tôi thực sự không biết nhưng khi tôi mở nó nó cho thấy như thế này: SQL * Plus phiên bản 10.1.0.4.2 là nó không phải 12 c
nikhil sugandh

đúng - bạn đang sử dụng có thể sử dụng phiên bản 10.1.xxx, bạn có thể SELECT * FROM V $ VERSION
mancini0

10

chúng ta có 3 lựa chọn để lấy hàng đầu tiên trong bảng Oracle DB.

1) select * from table_name where rownum= 1là cách tốt nhất

2) select * from table_name where id = ( select min(id) from table_name)

3)

select * from 
    (select * from table_name order by id)
where rownum = 1

Cảm ơn vì câu trả lời: theo điểm 3) "nowrum = 1" có lẽ nên được đổi thành "rownum = 1".
Andre Nel

7

Theo những gì tôi biết, dualbảng trong Oracle là một bảng đặc biệt chỉ có một hàng. Vì vậy, điều này sẽ đủ:

SELECT user
FROM dual

rằng ta không thật sự chọn sử dụng từ kép nên cung cấp cho bạn tất cả những người sử dụng
Ben


1
.. và vừa dùng thử trên hệ thống của tôi, hoạt động như ypercube và tất cả các đề cập đến tài liệu liên quan. @Ben
Sathyajith Bhat

1
@Ben kép không phải là dạng xem danh mục, nó sẽ không hiển thị "tất cả người dùng". Bạn sẽ sử dụng chế độ xem như ALL_USERS cho mục đích đó.
makrom

7

👌 Câu trả lời là:

Bạn nên sử dụng truy vấn lồng nhau như:

SELECT *
FROM ANY_TABLE_X 
WHERE ANY_COLUMN_X = (SELECT MAX(ANY_COLUMN_X) FROM ANY_TABLE_X) 

=> Trong PL / SQL "ROWNUM = 1" KHÔNG bằng "TOP 1" của TSQL.

Vì vậy, bạn không thể sử dụng truy vấn như sau: "select * from any_table_x where rownum = 1 order by any_column_x;" Bởi vì oracle lấy hàng đầu tiên sau đó áp dụng thứ tự theo mệnh đề.


1
Vui lòng thêm một số giải thích cho câu trả lời của bạn
hgwhittle

Cú pháp bất thường nên tránh mà không có lý do chính đáng. Trong trường hợp này, sẽ hữu ích nếu cung cấp trường hợp thử nghiệm hoặc số lỗi. Tôi mơ hồ nhớ lại một số vấn đề kỳ lạ với rownum = 1, nhưng chúng ta không nên để các lỗi cũ ảnh hưởng đến mã của chúng ta nữa.
Jon Heller

7
@hgwhittle, Lý do Fuat đúng là vì ROWNUM không quan tâm đến 'đặt hàng theo', nó chỉ lấy bản ghi đầu tiên mà nó có thể tìm thấy và trả về ngay lập tức. Vì vậy, nói cách khác, bộ định lượng ROWNUM không có bất kỳ sự tôn trọng nào đối với lệnh "Đặt hàng theo". Tôi ước đó không phải là trường hợp nhưng Fuat là đúng, sử dụng truy vấn lồng nhau.
Eric Milliot-Martinez

5

Không có limit 1điều kiện (đó là MySQL / PostgresSQL) trong Oracle, bạn cần chỉ định where rownum = 1.


5

"FirstRow" Là một hạn chế và do đó nó nằm trong wheremệnh đề không có trong selectmệnh đề. Và nó được gọi là rownum

select * from dual where rownum = 1;

1
Lưu ý rằng điều này sẽ không hoạt động như mong đợi khi kết hợp với ORDER BY, vì thứ tự chỉ xảy ra sau mệnh đề where. Nói cách khác, để lên đầu một truy vấn được sắp xếp nhất định, rownum hoàn toàn vô dụng.
Nyerguds

@Nyerguds, điều này chỉ đúng một nửa. Bạn có thể sử dụng thứ tự trước Wherevới một truy vấn Xem.
gdoron đang hỗ trợ Monica

4
Cái gì vậy SELECT * FROM (SELECT * FROM ... WHERE ... ORDER BY ...) WHERE ROWNUM = 1? Chà, điều đó có thể hiệu quả, nhưng nó trông khá ngớ ngẩn, tbh.
Nyerguds

2

Nếu bất kỳ hàng nào cũng vậy, hãy thử:

select max(user)  
from table;

Không có mệnh đề where.


9
Chắc chắn nó sẽ chỉ mất vài giây để bạn có thể cố gắng mà ra cho chính mình
Matt Donnan

1
select name, price
  from (
    select name, price, 
    row_number() over (order by price) r
      from items
  )
where r between 1 and 5; 

1

select a.user from (select user from users order by user) a where rownum = 1

sẽ hoạt động tốt nhất, một tùy chọn khác là:

select a.user 
from ( 
select user, 
row_number() over (order by user) user_rank, 
row_number() over (partition by dept order by user) user_dept_rank 
from users 
) a 
where a.user_rank = 1 or user_dept_rank = 2

trong các tình huống mà bạn muốn các tập hợp con khác nhau, nhưng tôi đoán bạn cũng có thể sử dụng RANK()Nhưng tôi cũng thích row_number() over(...)vì không cần nhóm.


0

Nếu bạn chỉ muốn lấy lại hàng đầu tiên của kết quả được sắp xếp với ít truy vấn con nhất, hãy thử cách này:

select *
  from ( select a.*
              , row_number() over ( order by sysdate_col desc ) as row_num
           from table_name a )
  where row_num = 1;

Trong đó sysdate_col sẽ là tên của bất kỳ cột nào bạn muốn sắp xếp và tất nhiên, table_name sẽ là tên của bảng mà bạn muốn dữ liệu được sắp xếp đến từ đó.
Jody Fedor

-1

Linh hoạt hơn select max()là:

select distinct first_row(column_x) over (order by column_y,column_z,...) from Table_A
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.