【问题标题】:T-Sql Select * Between 30% and 40%T-Sql 选择 * 在 30% 和 40% 之间
【发布时间】:2010-07-09 15:30:19
【问题描述】:

问题

  • 如何编写一个 T-SQL 存储过程,让我可以选择 X% 和 Y% 之间的行百分比?
  • 所以基本上我想选择介于 30 PERCENT 和 40 PERCENT 之间的行.....

我知道您可以执行以下操作,但显然这不会让 met 指定 2 个百分比之间的一组行。

SELECT TOP 50 PERCENT * FROM tblAssets 

非常感谢您的帮助。

【问题讨论】:

    标签: sql sql-server sql-server-2005 tsql stored-procedures


    【解决方案1】:

    更新答案

    declare @NumRecords int
    SELECT @NumRecords = COUNT(*) FROM tblAssets;
    
    With Vals As
    (
    SELECT tblAssets.AssetId ...
    , ROW_NUMBER() OVER ( order by tblAssets.AssetId) as RN
      FROM tblAssets
    )
    
    SELECT  tblAssets.AssetId ...
    FROM vals 
    Where RN between 0.3*@NumRecords and 0.4*@NumRecords
    

    我已经更新了我的答案,因为下面我的原始答案有 2 个问题

    1. 性能 - 被嵌套的TOP 解决方案击败
    2. 准确性 - NTILE 有一个我不知道的意外方面

    如果一个分区的行数 不能被 integer_expression,这将导致 两个大小相差一个的组 成员。更大的团体先于 按指定顺序排列的较小组 通过 OVER 子句。例如,如果 总行数为 53 并且 组数为五,第一 三组将有 11 行,并且 剩下的两个组将有 10 行 每个。

    与嵌套的TOP 解决方案相比,我得到了以下值。

    SET STATISTICS IO ON
    SET STATISTICS TIME ON;
    
    DECLARE @NumRecords int
    SELECT @NumRecords = COUNT(*) FROM [master].[dbo].[spt_values];
    
    WITH Vals As
    (
    SELECT  [number]
    , ROW_NUMBER() OVER ( order by [number]) as RN
      FROM [master].[dbo].[spt_values]
    )
    
    SELECT [number] FROM vals Where RN
     BETWEEN 0.30*@NumRecords AND 0.40*@NumRecords
    

    给予

    表'spt_values'。扫描计数 1, 逻辑读取 8,物理读取 0, read-ahead 读取 0,lob 逻辑读取 0, lob 物理读取 0, lob 预读为 0。

    表 'spt_values'。扫描计数 1,逻辑 读取 5,物理读取 0,预读 读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读 0.

    SELECT TOP 25 PERCENT [number] FROM
    (
    SELECT TOP 40 PERCENT  [number]
    FROM  [master].[dbo].[spt_values]
    ORDER BY [number]  ASC
    ) TOP40
    ORDER BY [number] DESC
    

    给予

    表“工作台”。扫描计数 1, 逻辑读取 4726,物理读取 0, read-ahead 读取 0,lob 逻辑读取 0, lob 物理读取 0, lob 预读为 0。

    表 'spt_values'。扫描计数 1,逻辑 读取 8,物理读取 0,预读 读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读 0.

    原答案

    With Vals As
    (
    SELECT tblAssets.AssetId ...
    , NTILE (100)  OVER ( order by tblAssets.AssetId) as Pct
      FROM tblAssets 
    )
    
    SELECT * FROM vals Where Pct between 30 and 40
    

    【讨论】:

    • +1:很好。我真的需要学习 SQL Server 中所有的新 OVER 函数。我在想 TOP 25 PERCENT 在 TOP 40 PERCENT 之后的 DESC 顺序。 NTILE 看起来干净多了。
    • 有趣!前几天我在想,如果没有能力定义自己的存储桶,NTILE 就毫无用处......
    • @Goober - 是的。我只想对照汤姆建议的答案检查执行计划。我会让你知道结果。
    • 我不太确定我是否理解语法......我对 T-SQl 相当陌生。为什么在“SELECT tblAssets.AssetId”之后加上“...” - 假设它不是语法
    • @Goober - 因为我从不使用 '*' 所以这只是一个指示,用你的实际列列表替换 ...!
    【解决方案2】:

    我自己想出了这个......

    SELECT TOP 40 *  
        INTO #TOP40
        FROM CCDtblAssets
    
     SELECT * FROM #TOP40
    WHERE ASSETID NOT IN   
    (SELECT TOP 30 ASSETID FROM #TOP40)
    

    虽然我确实喜欢 Martins Answer。

    【讨论】:

      猜你喜欢
      • 2017-07-14
      • 2018-06-29
      • 2013-11-28
      • 2012-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-13
      相关资源
      最近更新 更多