SQL左连接避免空条目

Posted

技术标签:

【中文标题】SQL左连接避免空条目【英文标题】:SQL left join avoid null entries 【发布时间】:2020-09-10 20:36:18 【问题描述】:

我有一个表:我想留下的电话加入到基表客户(customer_id 作为 PK)。加入后我得到重复的行。我需要根据描述列的查询将号码列排列为电话号码、传真号码和手机号码 3 个单独的列。

电话:

这是我尝试过的

select cust.customer_id, customer_phone_id,
CASE
    WHEN description like '%OFFICE%' or description like '%PHONE%' THEN number
    ELSE null
END AS [Phone Number],
CASE
    WHEN description like '%FAX%' THEN number
    ELSE null
END AS [Fax Number],
CASE
    WHEN description like '%CELL%' or description like '%MOBILE%' THEN number
    ELSE null
END AS [Cell Number] 
from customer cust 
left join customer_phone ph on cust.customer_id=ph.customer_id and ph.number is not null
order by customer_phone_id desc

但是我想避免将这些放在多行中

我希望最后只有一行包含所有这些值。 这就是我想要的结果:

提前致谢

【问题讨论】:

您想要哪个 customer_phone_id? 您可以在每个 CASE 上使用 MAX,按 customer_id 分组。但是您需要删除 customer_phone_id (或 usa MAX 甚至在那里)。 @Aww_Geez:对不起,我忘了提及,我想将 MAX id 作为最新条目 (customer_phone_id)。如果电话号码为空,我可以选择最近的第二个。事实上,只要我们获得所有 3 个条目,实际上并没有真正重视这一点 请use text, not images/links, for text--including tables & ERDs。仅将图像用于无法表达为文本或增强文本的内容。在图片中包含图例/键和说明。 请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出您可以给出的最少代码,即您显示的代码可以通过您显示的代码扩展为不正常。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。 How to Ask 停止尝试编写您的总体目标并从给定的代码中解释您的期望以及原因。 【参考方案1】:

你想要条件聚合:

select 
    c.customer_id, 
    max(cp.customer_phone_id) customer_phone_id,
    max(case when cp.description like '%OFFICE%' or cp.description like '%PHONE%' then cp.number end) as phone_number,
    max(case when cp.description like '%FAX%' then cp.number end) as fax_number,
    max(case when cp.description like '%CELL%' or cp.description like '%MOBILE%' then cp.number end) as cell_number
from customer c
left join customer_phone cp on c.customer_id = cp.customer_id 
group by c.customer_id
order by customer_phone_id desc

【讨论】:

您还需要汇总 customer_phone_id (或删除它),因为它是独一无二的......但从最后的评论认为您还需要 MAX 【参考方案2】:

这是非常快速和肮脏的,但可能是您正在寻找的。 . .它会将所有内容“折叠”成一行,假设您要查找的字段每次出现 1 个。

对于 customer_phone_id,我删除了 customer_phone_id 字段末尾的数字,因为我们知道 customer_id + 1 的下划线长度。





select 
    cust.customer_id, 
    CONCAT(cust.customer_id, '_', MAX(RIGHT(customer_phone_id,  LEN(customer_phone_id)-1-LEN(customer_id)))) customer_phone_id,
    MAX(CASE WHEN description like '%OFFICE%' or description like '%PHONE%' THEN number
        ELSE null END) AS [Phone Number],
    MAX(CASE WHEN description like '%FAX%' THEN number
        ELSE null END) AS [Fax Number],
    MAX(CASE WHEN description like '%CELL%' or description like '%MOBILE%' THEN number
        ELSE null END) AS [Cell Number] 
from 
    customer cust 
    left join customer_phone ph on cust.customer_id=ph.customer_id and ph.number is not null
group by
    cust.customer_id
order by 
    customer_phone_id desc

【讨论】:

为什么干脆不 MAX(customer_phone_id)? 因为老实说,我不知道使用字符串时 MAX 是如何工作的。 由数字组成的字符串在每个数字上从 0 到 9 排序,因为根是相同的,唯一的变量是最后一个数字......如果它们保持在 0 之间,MAX 将返回更大的一个-9。例如,如果将退出 _10,它将是 _2 的次要 所以只要 '_' 后面的数字保持在 10 以下,就可以单独使用最大值? 是的,但要使整个查询正常工作 customer_phone_id(电话不为空)必须最大为 3,4 数字将导致 MAX(CASE ....) 隐藏现有电话数字(取最大值,遵循相同的规则)【参考方案3】:
select
   cust.customer_id,
   ph_cell.customer,
   ''phone_number,
   ph_fax.number Fax_number,
   ph_cell.number Cell_number 
from
   customer cust 
   left join
      phone ph_cell 
      on cust.customer_id = ph_cell.customer 
      and ph_cell.descriptions = 'cell' 
   left join
      phone ph_fax 
      on cust.customer_id = ph_fax.customer 
      and ph_fax.descriptions = 'fax'

【讨论】:

以上是关于SQL左连接避免空条目的主要内容,如果未能解决你的问题,请参考以下文章

mysql左连接没有数据还会查出来吗

在 Spark 结构化流中将数据内部连接到左连接 DataFrame 时丢失条目

Spark 2.2 空安全左外连接空指针异常

选择带有“is null”子句的查询和子选择/左连接不返回结果

如何使用 MySQL 展平左连接的结果?

左外连接和右外连接的区别