SQL生成一个包含多个前X个记录的表,其中top#来自另一个表

时间:2016-04-08 19:50:22

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

我正在使用SQL Server 2012.

我需要生成一个输出,其中包含多个" top"的结果。查询,其中#of" top"每个查询中返回的行因另一个表中的值而异。

我的第一个表格,称之为Table1,是一个参考表格,其中NUMBER告诉我每个独特的市场/措施需要从另一个表格中返回多少顶行。

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      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行,依此类推,全部在一个表格中,好像我已经" UNIONed" (?)每个查询单独。

如何动态执行此操作,而不必对表1中的每个MARKET / MEASURE进行UNION个别查询(其中超过1000个)?

我觉得答案是使用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中带回多个值,而我无法弄清楚如何将其运行到"运行&# 34;对于每个MARKET / MEASURE组合。

非常感谢。

2 个答案:

答案 0 :(得分:2)

这是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

答案 1 :(得分:1)

对于处于同样困境的任何人,我想出了另一种完成同样事情的方法,使用ROW_NUMBER()窗口函数而不是尝试动态使用TOP。我们的想法是在Table2中添加一个行号,按市场划分。测量并按姓氏排序,然后将Table1.Number连接到Table2,并仅选择行号小于Table1.Number的行,从而返回" top"根据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