sql - 使用 Union 和 Order By 而不重复
问题描述
我正在使用 anUNION
来合并精确搜索和模糊搜索的结果。我希望完全匹配位于顶部,其他结果按列排序。我发现这个解决方案可以正常工作UNION ALL
,但是通过添加rank
列我失去了UNION
(没有全部)的属性以从结果集中删除完全匹配的重复项。
有没有一种优雅的方法来解决这个问题,还是我必须手动删除重复项?
作为参考,我的简化查询:
SELECT 1 AS [Rank], [CallerID]
FROM [PHONE]
WHERE [CallerID] = '12345'
UNION
SELECT 2 AS [Rank], [CallerID]
FROM [PHONE]
WHERE [CallerID] LIKE '12%' AND ABS(LEN([CallerID]) - LEN('12345')) < 3
ORDER BY [Rank] ASC, [CallerID] ASC
结果可能如下所示:
Rank CallerID
----------- --------------------
1 12345
2 123
2 1233
2 1234
2 12345 <- I don't want this line
2 1236
备注:设置DISTINCT
我的来电显示不会解决问题,因为我的真实查询有更多列。我真的只想删除我通过UNION
.
解决方案
将您现有的查询放在 CTE 中(这里我将您的示例数据放在那里),然后使用 aROW_NUMBER()
和 a 进一步WHERE
过滤结果:
with OriginalQuery as (
select 1 as Rank, 12345 as CallerID union all
select 2 ,123 union all
select 2,1233 union all
select 2,1234 union all
select 2,12345 union all
select 2,1236
), Preferred as (
select *,ROW_NUMBER() OVER (
PARTITION BY CallerID /* other columns too? */
ORDER BY RANK
) as rn
from OriginalQuery
)
select
*
from
Preferred
where
rn = 1
order by Rank,CallerID
如前所述,对于此数据,您可能必须单独向PARTITION
ifCallerID
不是键添加更多/调整列。
当然,如果您的基础数据中没有任何重复项,并且您获得重复项的原因仅仅是因为您正在运行两次搜索并组合结果,那么执行起来要简单得多:
SELECT [CallerID]
FROM [PHONE]
WHERE
CallerID = '12345' OR
([CallerID] LIKE '12%' AND ABS(LEN([CallerID]) - LEN('12345')) < 3)
ORDER BY CASE WHEN CallerID='12345' THEN 0 ELSE 1 END, [CallerID] ASC
您将这两个搜索结合起来,而不是结合它们的结果,然后用于CASE
在ORDER BY
.
推荐阅读
- amazon-s3 - 我们可以将来自 Kinesis 数据流的数据直接流式传输到 Amazon s3 还是仅通过 Kinesis Firehose?
- bash - bash - 提取以数字开头的部分变量
- php - PHP:通过包含mime类型的文件
- composer-php - 在 composer.json 中为特定供应商的所有包设置冲突
- phpword - 使用 PHPWord 0.16 库中的 addHtml() 控制图像大小
- azure - 在 VNET 中使用 ACI 的传出 ip
- javascript - 为什么 scrollintoview() 在桌面和移动设备上的行为不同?
- docker - 为什么我的环境不适合 istio ingress agteway?
- excel - 使用 VBA Selenium webdriver 刮一张桌子,但是太慢了
- javascript - 使用 javascript 全局设置 toastr 选项