如何针对单列执行SELECT DISTINCT并排除NULL值?SQL问题求助
解决你的SQL查询问题
嗨,我来帮你搞定这个查询需求!先明确下你的核心诉求:
- 对于
PRODUCT列非NULL的记录,只保留每个PRODUCT对应的**第一条(按ID升序)**数据 - 对于
PRODUCT列为NULL的记录,要全部保留 - 同时只筛选
SKU以FOO开头的行
先分析你原有SQL的问题
你之前的SQL用了PARTITION BY PRODUCT,但SQL里NULL值会被视为相同的分组键,所以所有PRODUCT为NULL的行会被分到同一个分区里,ROW_NUMBER()会给它们标记1、2...,最后WHERE RowNumber=1就只留下了一条NULL行,这和你要保留所有NULL行的需求不符。
方案一:调整分区逻辑(推荐)
我们可以用CASE语句修改分区规则:让非NULL的PRODUCT按自身分组,NULL的PRODUCT用唯一的ID拼接成分区键,这样每个NULL行都单独成一个分区,它们的RowNumber自然都是1。
SELECT ID, SKU, PRODUCT FROM ( SELECT ID, SKU, PRODUCT, ROW_NUMBER() OVER ( PARTITION BY CASE WHEN PRODUCT IS NOT NULL THEN PRODUCT ELSE CONCAT('NULL_', ID) -- 用唯一ID做分区键,让每个NULL行单独分组 END ORDER BY ID ) AS RowNumber FROM MyTable WHERE SKU LIKE 'FOO%' ) AS a WHERE a.RowNumber = 1;
方案二:拆分查询再合并(更直观)
如果觉得上面的分区逻辑有点绕,也可以把两种情况分开查询,再用UNION ALL合并结果:
-- 第一部分:获取非NULL PRODUCT的第一条记录 SELECT ID, SKU, PRODUCT FROM ( SELECT ID, SKU, PRODUCT, ROW_NUMBER() OVER (PARTITION BY PRODUCT ORDER BY ID) AS RowNumber FROM MyTable WHERE SKU LIKE 'FOO%' AND PRODUCT IS NOT NULL ) AS a WHERE a.RowNumber = 1 UNION ALL -- 第二部分:获取所有PRODUCT为NULL的记录 SELECT ID, SKU, PRODUCT FROM MyTable WHERE SKU LIKE 'FOO%' AND PRODUCT IS NULL;
这两种方案都能得到你期望的结果:
1 FOO-23 Orange 3 FOO-24 Apple 5 FOO-25 null 6 FOO-25 null
内容的提问来源于stack exchange,提问作者Elham Azadfar
相关产品推荐
相关产品推荐

