平衡不同类型的结果记录受到TOP 100的限制

时间:2009-07-26 20:01:02

标签: sql tsql sql-server-2008

如果列表Records包含id intType intName varchar(50)列,我可以像这样进行搜索查询:

SELECT id, Type, Name
FROM Records
WHERE Name LIKE '%Foo%'

稍微调整一下表现,我只想给出有限的结果;目前为100 - 只需在语句中添加TOP 100即可。但是,这可能导致某些类型的记录未被充分表示,或者根本没有表示,如以下查询所示:

SELECT Type, COUNT(Type) FROM
    (SELECT id, Type, Name
    FROM Records
    WHERE Name LIKE '%Foo%') x
GROUP BY Type
ORDER BY Type

如果没有TOP 100,我可能会得到:

42  5
49  1
50  1
52  1
59  1
76  40
87  567
90  3

......和它一起:

42  5
49  1
50  1
52  1
59  1
76  26
87  65

这可能会导致用户断定不存在90类型的记录。

我更希望TOP表现不同:至少给我一个任何类型的结果,然后继续添加它们直到达到计数。例如,427687的结果会更少,但会显示90

理想情况下,我还想为用户提供“x此类型的更多结果”UI元素。

我是否必须完全放弃TOP来完成此任务?

3 个答案:

答案 0 :(得分:3)

WITH RecordsWithRn AS (
SELECT id, Type, Name,
   ROW_NUMBER() OVER (PARTITION BY Type ORDER BY ... intra-type ordering ...) as rn
        FROM Records
        WHERE Name LIKE '%Foo%') 
SELECT TOP 100 id, Type, Name
   FROM RecordsWithRn
   ORDER BY RN, ... inter-type ordering ...

这会给你一百条记录。假设少于一百种类型,您将至少拥有每种类型中的一种。使用ORDER BY for ROW_NUMBER()来控制类型中记录的ROW_NUMBER的顺序。最后的ORDER BY,按先前分配的row_number排序,然后根据需要添加其他条件,以控制每个row_number的类型之间的记录顺序。

编辑:要获取未显示类型的记录数:

WITH RecordsWithRn AS (
   SELECT id, Type, Name,
      ROW_NUMBER() OVER (PARTITION BY Type ORDER BY Type) as rn,
      COUNT(*) OVER (PARTITION BY Type) as CountType
   FROM Records
   WHERE Name LIKE '%Foo%')
, Top100Records as (
   SELECT TOP 100 id, Type, Name, CountType
   FROM RecordsWithRn
   ORDER BY RN)
select Id, Type, Name, 
    CountType - (COUNT(*) over (PARTITION BY Type)) as CountTypeNotIncluded
from Top100Records

答案 1 :(得分:1)

WITH cte AS (
SELECT id, Type, Name,
   ROW_NUMBER() OVER (PARTITION BY Type ORDER BY Type) as rn
        FROM Records
        WHERE Name LIKE '%Foo%') 
SELECT *
   FROM cte
   WHERE rn <= 100;

这将从每个类型获得最多100条记录。请注意,这绝不意味着查询会更快,实际上它可能会更慢。它取决于可用的索引,表中的数据以及客户端能够处理结果的速度。

如果您可以显示每种类型的总数,则必须计算它:

WITH totals AS (
    SELECT Type, COUNT(*) AS count
            FROM Records
            WHERE Name LIKE '%Foo%'
     GROUP BY Type) 
SELECT * FROM totals;

然后加入两个结果:

WITH cte AS (
    SELECT id, Type, Name,
       ROW_NUMBER() OVER (PARTITION BY Type ORDER BY Type) as rn
            FROM Records
            WHERE Name LIKE '%Foo%')
, totals AS (
        SELECT Type, COUNT(*) AS count
                FROM Records
                WHERE Name LIKE '%Foo%'
         GROUP BY Type) 
    SELECT *
       FROM cte c 
       JOIN totals t on c.Type = t.Type
       WHERE c.rn <= 100;

答案 2 :(得分:0)

你可以打两个电话。第一个是[type]和count([type])。这将提供所有可用类型的唯一列表以及它们的计数,以向用户提供更多信息。之后,在用户请求时按类型进行调用。