如果列表Records
包含id int
,Type int
和Name 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
表现不同:至少给我一个任何类型的结果,然后继续添加它们直到达到计数。例如,42
,76
和87
的结果会更少,但会显示90
。
理想情况下,我还想为用户提供“x此类型的更多结果”UI元素。
我是否必须完全放弃TOP
来完成此任务?
答案 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])。这将提供所有可用类型的唯一列表以及它们的计数,以向用户提供更多信息。之后,在用户请求时按类型进行调用。