【问题标题】:How do I SELECT TOP X where it INCLUDES records based on a criteria?如何根据条件选择包含记录的 TOP X?
【发布时间】:2012-09-04 17:23:06
【问题描述】:

我有一个表,有多个列,包括一个名为“PolicyNumber”的列

这是一个示例:

PolicyNumber

NYH1111
NYD2222
SCH3333
SCS4444
LUH5555
LUS6666
ALH7777
ALW8888
VAH9999
AKH0000
...
NYH1010
NYD2318

此表中有 1,000 多条记录,记录包含每种保单编号类型中的几种。例如,以“NYH”开头的多项政策或以“VAH”开头的多项政策。

可能的策略类型在这里:

NYH
NYD
SCH
SCS
LUH
LUS
ALH
ALW
VAH
AKH

如何执行 SELECT TOP 300,其中至少包含每种策略类型中的一种?请记住,保单类型是保单编号的前 3 个字母。

这甚至可能吗?这样做的目的是我必须从生产中获取 300 条记录以转储到测试环境中,并且我需要包含每个策略中的至少 1 条。在我至少有一个之后,它可以完全随机化。

【问题讨论】:

  • 你试过GROUP BY SUBSTRING(PolicyNumber, 1, 3)吗?
  • group by 在这种情况下不会起作用吗?它将所有类似的策略都扔到顶部,从而删除“随机”选择
  • 我确定您的要求是可能的,但作为替代方案,您是否考虑过为每种类型选择前 50 名? WHERE PolicyID LIKE 'NYH%' 为每个,然后将您的结果合并到测试台。
  • @DJQuimby DISTINCT SUBSTRING(... ...ORDER BY RAND() 怎么样?
  • @DJQuimby,我想我可以这样做并运行多个查询(每种策略类型 1 个)...尽管对此进行 1 个查询会很好!

标签: sql tsql select


【解决方案1】:

你可以试试这个:

在这个解决方案中,首先有newid(),您可以通过每次运行生成随机顺序。

为了实现“每个政策中至少一个”的目标,我创建了AtLeastOne 列。这将从随机的CTE 表中为每个唯一的三个字母在开头选择第一个。如果当前Policy 等于第一个选定的值,则它得到 1,否则为 0。因此,使用此逻辑,您可以从每个唯一的三个字母中选择 随机的第一个。

注意:如果您只需要 Policy 字段,也可以将此逻辑直接放入 Order By 部分。 (我就是这样做了例子,让背后的逻辑可见)

在最后一步中,您只需通过AtLeastOne Desc 订购,然后随机订购ID

WITH CTE_Policy
AS
(
  SELECT newid() as  ID, Policy
  FROM Code
)
SELECT TOP 300
Policy,
CASE WHEN Policy = (SELECT TOP 1 Policy FROM cte_Policy c
                    WHERE SUBSTRING(c.Policy,1,3) = 
                      SUBSTRING(CTE_Policy.Policy,1,3))
THEN 1 ELSE 0 END  AS AtLeastOne

FROM CTE_Policy
ORDER BY AtLeastOne DESC, ID

这是SQLFiddle demo

【讨论】:

    【解决方案2】:

    在我的脑海中,你可以这样做:

    SELECT TOP 30 Column1, Column2, Column3, PolicyNumber
    FROM YourTable
    WHERE PolicyNumber LIKE 'NYH%'
    
    UNION 
    
    SELECT TOP 30 Column1, Column2, Column3, PolicyNumber
    FROM YourTable
    WHERE PolicyNumber LIKE 'NYD%'
    
    UNION
    
    /* ... remaining eight policy types go here */ 
    
    ORDER BY PolicyNumber /* Or whatever sort order you want */
    

    它每次都会给你每种类型的 30 个,而不是一个类型的 X 和另一种类型的 Y。

    【讨论】:

      【解决方案3】:

      我想到的一种快速方法.. 下面的查询将只获取每种策略类型的 1 条记录

       SELECT TOP 300 *
      
       FROM   ( SELECT *,rank1= ROW_NUMBER () OVER (PARTITION BY LEFT (PolicyNo,3) ORDER BY GETDATE ()) FROM MyTable
              ) AS t1
      
       WHERE  t1.rank1 = 1
      

      【讨论】:

        【解决方案4】:

        在 SQL Server 2005+ 上试试这个:

        ;WITH CTE AS
        (
            SELECT  LEFT(PolicyNumber) PolicyType, PolicyNumber, 
                    ROW_NUMBER() OVER(PARTITION BY LEFT(PolicyNumber) ORDER BY NEWID()) RN
            FROM YourTable
        )
        SELECT TOP 300 PolicyNumber
        FROM CTE
        ORDER BY RN, NEWID()
        

        【讨论】:

          【解决方案5】:

          借自 ClearLogic +1 如果可行,请给 ClearLogic 支票

          WHERE t1.rank1 = 1 的问题是,如果少于 300 个唯一值,它将停止在 300 个以下

           SELECT TOP 300 t1.PolicyNo
          
           FROM   ( SELECT PolicyNo, rank1= ROW_NUMBER () 
                    OVER (PARTITION BY LEFT (PolicyNo,3) ORDER BY NEWID()) 
                    FROM MyTable
                  ) AS t1
          
           order by t1.rank, t1.PolicyNo
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-11-27
            • 2016-05-01
            • 2018-06-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多