【发布时间】:2010-09-01 10:38:52
【问题描述】:
我有一个表,我需要检索第二行的 ID。如何实现?
Top 2 我选择了前两行,但我只需要第二行
【问题讨论】:
标签: sql-server tsql
我有一个表,我需要检索第二行的 ID。如何实现?
Top 2 我选择了前两行,但我只需要第二行
【问题讨论】:
标签: sql-server tsql
在 SQL Server 2012+ 中,您可以使用 OFFSET...FETCH:
SELECT
<column(s)>
FROM
<table(s)>
ORDER BY
<sort column(s)>
OFFSET 1 ROWS -- Skip this number of rows
FETCH NEXT 1 ROWS ONLY; -- Return this number of rows
【讨论】:
假设 SQL Server 2005+ 是如何获得 just 第二行的示例(我想您可能会问 - 这就是 top 不适合您的原因?)
set statistics io on
;with cte as
(
select *
, ROW_NUMBER() over (order by number) as rn
from master.dbo.spt_values
)
select *
from cte
where rn = 2
/* Just to add in what I was running RE: Comments */
;with cte as
(
select top 2 *
, ROW_NUMBER() over (order by number) as rn
from master.dbo.spt_values
)
select *
from cte
where rn = 2
【讨论】:
TOP 2,就像我在我的回答中所做的那样(除了 ROW_NUMBER()),您可以将查询效率提高大约 6 倍。使用 @987654326 @我的版本的 TotalSubtreeCost 为 0.0125678,而此版本(不使用 TOP 2)的值为 0.06937763,同时返回相同的结果集。
set statistics io on 时,它看起来并没有任何区别。自从stackoverflow.com/questions/3424650/…
set statistics io on 运行它时,您的版本在添加TOP 2 后使用Table 'spt_values'. Scan count 1, logical reads 18, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 运行,我得到Table 'spt_values'. Scan count 1, logical reads 6, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 另外,set showplan_all on 表明执行计划不同。
Table 'spt_values'. Scan count 1, logical reads 6, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 那么可能是依赖于服务包的行为?
Table 'spt_values'. Scan count 1, logical reads 18, physical reads 1, read-ahead reads 16, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.,第二个版本(TOP 2)有:Table 'spt_values'. Scan count 1, logical reads 6, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.。当我运行select count(*) from master.dbo.spt_values 我得到2346,你得到了什么?如果行数相同,则可能归结为硬件和内存使用情况。
如果字段 ID 是唯一的,则不需要行号函数。
SELECT TOP 1 *
FROM (
SELECT TOP 2 *
FROM yourTable
ORDER BY ID
) z
ORDER BY ID DESC
【讨论】:
z 在第二个 ORDER BY 子句之前是必需的吗?
使用ROW_NUMBER() 对行进行编号,但使用TOP 仅处理前两行。
试试这个:
DECLARE @YourTable table (YourColumn int)
INSERT @YourTable VALUES (5)
INSERT @YourTable VALUES (7)
INSERT @YourTable VALUES (9)
INSERT @YourTable VALUES (17)
INSERT @YourTable VALUES (25)
;WITH YourCTE AS
(
SELECT TOP 2
*, ROW_NUMBER() OVER(ORDER BY YourColumn) AS RowNumber
FROM @YourTable
)
SELECT *
FROM YourCTE
WHERE RowNumber=2
输出:
YourColumn RowNumber
----------- --------------------
7 2
(1 row(s) affected)
【讨论】:
我猜您使用的是 SQL 2005 或更高版本。第2行选择前2行,使用ORDER BY ROW_COUNT DESC,将第2行排列为第一,然后使用TOP 1选择
SELECT TOP 1 COLUMN1, COLUMN2
from (
SELECT TOP 2 COLUMN1, COLUMN2
FROM Table
) ORDER BY ROW_NUMBER DESC
【讨论】:
row_number 来自哪里?
您可以使用OFFSET 和FETCH NEXT
SELECT id
FROM tablename
ORDER BY column
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY;
注意:
OFFSET 只能与 ORDER BY 子句一起使用。它不能用于其 拥有。
OFFSET 值必须大于或等于零。它不可能是 负数,否则返回错误。
OFFSET 参数用于标识返回的起点 结果集中的行。基本上,它排除了第一组 记录。
FETCH 参数用于返回一组行数。拿来 不能单独使用,与OFFSET结合使用。
【讨论】:
with T1 as
(
select row_number() over(order by ID) rownum, T2.ID
from Table2 T2
)
select ID
from T1
where rownum=2
【讨论】:
在 SELECT 中使用 TOP 2 以获得所需的输出行数。
这将按创建数据的顺序返回。如果您有日期选项,您可以按日期订购,并附上TOP n 条款。
获取前 2 行;
SELECT TOP 2 [Id] FROM table
按某个字段获取前 2 行的顺序
SELECT TOP 2 [ID] FROM table ORDER BY <YourColumn> ASC/DESC
只获取第二行;
WITH Resulttable AS
(
SELECT TOP 2
*, ROW_NUMBER() OVER(ORDER BY YourColumn) AS RowNumber
FROM @Table
)
SELECT *
FROM Resultstable
WHERE RowNumber = 2
【讨论】:
Select top 2 [id] from table Order by [id] desc 应该给你希望你添加的最新两行。
但是,您必须特别注意 order by 子句,因为它将决定返回的第一行和第二行。
如果要像这样更改查询:
Select top 2 [id] from table Order by ModifiedDate desc
你可以得到两个不同的行。您必须决定在 order by 语句中使用哪一列。
【讨论】:
我有一个比上面那些更简单的方法。
DECLARE @FirstId int, @SecondId int
SELECT TOP 1 @FirstId = TableId from MyDataTable ORDER BY TableId
SELECT TOP 1 @SecondId = TableId from MyDataTable WHERE TableId <> @FirstId ORDER BY TableId
SELECT @SecondId
【讨论】:
如果您只是想要 TOP 2,当然 TOP 会出现,但如果您需要单独使用它们以便您可以使用这些值做一些事情,那么请使用 ROW_NUMBER,它可以让您更好地控制要选择的行
ps。我这样做是因为我不确定 OP 是否在选择中的简单 TOP 2 之后。 (我可能错了!)
-- Get first row, same as TOP 1
SELECT [Id] FROM
(
SELECT [Id], ROW_NUMBER() OVER (ORDER BY [Id]) AS Rownumber
FROM table
) results
WHERE results.Rownumber = 1
-- Get second row only
SELECT [Id] FROM
(
SELECT [Id], ROW_NUMBER() OVER (ORDER BY [Id]) AS Rownumber
FROM table
) results
WHERE results.Rownumber = 2
【讨论】:
SELECT *
FROM (
SELECT top 3 *
, ROW_NUMBER() OVER (ORDER BY [newsid] desc) AS Rownumber
FROM news
where (news_type in(2,12))
) results
WHERE results.Rownumber = 1
// news 表名和 newsid 列名
【讨论】:
这也很有用:
SELECT t.*
FROM (
SELECT e1.*
, row_number() OVER (ORDER BY e1.Rate DESC) AS _Rank
FROM
HumanResources.EmployeePayHistory AS e1
) AS t
WHERE t._Rank = 2
【讨论】:
有一个基于 SQLDiver 和 Taha Ali 的 cmets 的相对简单的解决方案。
假设有一个包含由函数 ORIGINAL_LOGIN() 检索到的“域\用户名”的字符串,我不需要域组件。
第一种方法
DECLARE @Login NVARCHAR(100)
SELECT @Login = 'domain\username'
-- SELECT @Login = ORIGINAL_LOGIN()
SELECT
VALUE
FROM
STRING_SPLIT(@Login, '\')
返回一个有 2 行的表。 第一行包含域,第二行包含请求的用户名。
使用
DECLARE @Login NVARCHAR(100)
SELECT @Login = 'domain\username'
-- SELECT @Login = ORIGINAL_LOGIN()
SELECT
VALUE
FROM
STRING_SPLIT(@Login, '\')
ORDER BY
(SELECT NULL)
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY;
准确返回临时表的第二行。
【讨论】:
另一个想法是这样的:
SELECT MIN(id) FROM
(
SELECT TOP 2(TAB.[id])
FROM TAB
where TAB.field1 =3
ORDER BY TAB.[creationDate] DESC
) AS TEST
)
【讨论】:
SELECT TOP 2 [Id] FROM table
【讨论】:
select *
from (
select ROW_NUMBER() OVER (ORDER BY Column_Name) as ROWNO, *
from Table_Name
) Table_Name
where ROWNO = 2
【讨论】: