【问题标题】:SQL Generate a table of multiple top X records, where top # comes from another tableSQL 生成多条top X记录的表,其中top#来自另一个表
【发布时间】:2016-04-13 02:49:01
【问题描述】:

我使用的是 SQL Server 2012。

我需要生成一个输出,其中包含多个“top”查询的结果,其中每个查询中返回的“top”行数根据另一个表中的值而变化。

我的第一个表,称为 Table1,是参考表,其中 NUMBER 告诉我对于每个唯一的 MARKET/MEASURE,我需要从另一个表返回多少顶行。

MARKET      MEASURE     NUMBER
------      -------      ------
MarketA     MeasureA    411
MarketA     MeasureB    396
MarketB     MeasureA    548
MarketB     MeasureC    424
MarketC     MeasureC    411

第二个表 Table2 列出了给定 MARKET/MEASURE 中每个人的详细信息,其中 MARKET 和 MEASURE 的组合是我的主键。任何给定的 MARKET/MEASURE 都有许多条目。

MARKET      MEASURE      LASTNAME      COMPLIANT
------      -------      --------      ---------
MarketA     MeasureA     Coppola       Y
MarketA     MeasureA     Winterbottom  N
MarketA     MeasureB     Scorsese      Y
MarketC     MeasureC     Tarr          Y

对于 Table1 中的每个值,我需要根据 LASTNAME 的升序从 Table2 返回那么多顶部行。例如,因为 Table1 的 MarketA/MeasureA 的 NUMBER 为 411,我的输出需要包含 Table2 中的 TOP 411 * 行(基于该市场中按 LASTNAME 升序排序的所有人员),以及 MarketA/ 的 TOP 396 行MeasureB,然后是 MarketB/MeasureA 的 TOP 548 行,依此类推,都在一个表中,就好像我已经“联合”(?)每个查询单独。

如何动态地执行此操作,而不必为表 1(其中超过 1000 个)中的每个 MARKET/MEASURE 单独查询?

感觉答案是用select表达式在TOP表达式中生成#,比如.....

select TOP (select NUMBER from TABLE2) *  
from TABLE1 t1
inner join TABLE2 t2 on t2.MARKET = T1.MARKET
                     and t2.MEASURE = T2.MEASURE 

...但显然我错过了几个步骤,因为 TOP 表达式将从 TABLE2 中带回多个值,我无法完全弄清楚如何让它为每个 MARKET/MEASURE 组合“运行”。

帮助非常感谢。

【问题讨论】:

    标签: sql-server tsql sorting dynamic sql-server-2012


    【解决方案1】:

    这就是APPLY 的用途

    SELECT
        *
    
    FROM
        Table1
        CROSS APPLY
        (
            SELECT TOP (Table1.Number)
                *
    
            FROM
                Table2
    
            WHERE
                Table1.Market = Table2.Market
                AND Table1.Measure = Table2.Measure
    
            ORDER BY
                LastName
        ) AS TopResults
    

    http://sqlfiddle.com/#!6/46b57/4

    【讨论】:

    • 我无法让它工作。显然我不能在 TOP 表达式中使用 (Table1.Number) 。当我将其更改为等效的子查询时(从 TABLE1 中选择 NUMBER),我之前遇到了同样的问题,该子查询将返回多个值。
    • 您的查询一定不正确,我添加了一个 sqlfiddle 来表明它有效。
    • 以上回答你的问题了吗?
    • 是的,我能够让它工作,它产生了预期的结果。我也在周末找到了另一种方法。如果有人正在查看此内容以供参考,我将添加我的答案,然后接受您的答案。感谢您的帮助。
    【解决方案2】:

    对于处于同样困境的任何人,我想出了另一种方法来完成同样的事情,使用 ROW_NUMBER() 窗口函数而不是尝试动态使用 TOP。想法是向Table2添加一个行号,按市场和度量分区并按姓氏排序,然后将Table1.Number连接到Table2,并仅选择行号小于Table1.Number的行,从而返回根据 Table1.Number 的“顶部”行数。

    with temp as (select 'rownum' = row_number() over(partition by t2.market, t2.measure)
                                                      order by t2.lastname)
                    , t2.*
                    , t1.number
                  from table2 t2
                  inner join table1 t1 on t1.market = t2.market
                                       and t1.measure = t2.measure)
    select *
    from temp
    where rownum <= number
    order by market, measure, rownum
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多