You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何简洁查询所有非空手机号均设标记的客户?

简洁实现你的客户查询需求

嘿,这个场景我碰到过!你现在的写法虽然能跑通,但确实太啰嗦了,尤其是以后要是再加手机号列,维护起来会很麻烦。给你分享两种更简洁且易维护的实现方式:

方法一:利用BIT类型特性简化判断

因为你的标记位是BIT类型(0/1),我们可以通过合并空值判断来简化条件,同时满足两个核心要求:至少一个非空手机号,且所有非空手机号的标记位都是1。

SELECT * 
FROM #Listing
WHERE 
    -- 核心判断:所有非空手机号的标记位都不能是0
    (COALESCE(Phone1 IS NOT NULL AND Phone1Flagged = 0, 0) +
     COALESCE(Phone2 IS NOT NULL AND Phone2Flagged = 0, 0) +
     COALESCE(Phone3 IS NOT NULL AND Phone3Flagged = 0, 0) +
     COALESCE(Phone4 IS NOT NULL AND Phone4Flagged = 0, 0)) = 0
    -- 确保至少有一个手机号非空
    AND (Phone1 IS NOT NULL OR Phone2 IS NOT NULL OR Phone3 IS NOT NULL OR Phone4 IS NOT NULL)

逻辑说明:

  • 对于每个手机号,如果它非空且标记位是0,就返回1,否则返回0(空手机号用COALESCE转成0)
  • 把这些值加起来,如果总和是0,说明没有任何非空手机号的标记位是0
  • 最后加上至少一个非空手机号的判断,排除全空的客户(比如id=1的Dave)

方法二:列转行(UNPIVOT)实现扩展性更强的查询

如果以后可能增加更多手机号列,推荐用这种方法——把分散的手机号和标记位列转成行,用聚合函数统一判断,扩展性拉满:

WITH CustomerPhones AS (
    SELECT 
        id, Customer,
        Phone, Flagged
    FROM #Listing
    -- 把手机号列转成行
    UNPIVOT (
        Phone FOR PhoneCols IN (Phone1, Phone2, Phone3, Phone4)
    ) p
    -- 把标记位列转成行
    UNPIVOT (
        Flagged FOR FlagCols IN (Phone1Flagged, Phone2Flagged, Phone3Flagged, Phone4Flagged)
    ) f
    -- 确保手机号和对应的标记位匹配(比如Phone1对应Phone1Flagged)
    WHERE RIGHT(p.PhoneCols, 1) = RIGHT(f.FlagCols, 1)
)
SELECT l.*
FROM #Listing l
JOIN (
    SELECT id
    FROM CustomerPhones
    GROUP BY id
    -- 至少一个非空手机号
    HAVING COUNT(Phone) > 0
    -- 所有非空手机号的标记位都是1(没有标记位为0的非空手机号)
    AND MAX(CASE WHEN Phone IS NOT NULL AND Flagged = 0 THEN 1 ELSE 0 END) = 0
) c ON l.id = c.id

逻辑说明:

  • 通过UNPIVOT把每一组手机号+标记位转成单独的行,让数据结构更规整
  • 分组后用聚合函数判断:COUNT(Phone) > 0确保有非空手机号;MAX(CASE...) = 0确保没有违规的标记位
  • 以后加Phone5/Phone6,只需要修改UNPIVOT里的列名即可,不需要改判断逻辑

两种方法都能得到你想要的结果:id=4的Bill和id=6的Andy。

内容的提问来源于stack exchange,提问作者ImmortalStrawberry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:03:53