Sql Left Join if Where 不存在

Posted

技术标签:

【中文标题】Sql Left Join if Where 不存在【英文标题】:Msql Left Join if Where not exists 【发布时间】:2021-03-24 11:10:09 【问题描述】:

我有以下问题。它工作得很好,除非 _billing_company 的行不存在。 如果_billing_company 不存在,我可以获得某种默认值或空值吗? 在下面的示例中,将显示 ID 为 1 的帖子,但不会显示 ID 为 2 的帖子,因为postmeta 中没有_billing_company 列。 我想获得所有帖子,无论是否所有 meta_keys 都存在。这怎么可能?

SELECT p.post_date
    , p.ID
    , m1.meta_value AS 'order_total'
    , m2.meta_value AS 'currency'
    , m3.meta_value AS '_billing_company'
    , m4.meta_value AS '_billing_first_name'
    , m5.meta_value AS '_billing_last_name'
FROM dawp_posts p
LEFT JOIN dawp_postmeta m1
    ON p.ID = m1.post_id
LEFT JOIN dawp_postmeta m2
    ON p.ID = m2.post_id
LEFT JOIN dawp_postmeta m3
    ON p.ID = m3.post_id
LEFT JOIN dawp_postmeta m4 
    ON p.ID = m4.post_id
LEFT JOIN dawp_postmeta m5
    ON p.ID = m5.post_id
WHERE p.post_type = 'shop_order' 
    AND p.post_status NOT LIKE 'wc-completed' 
    AND m1.meta_key = '_order_total'
    AND m2.meta_key = '_order_currency'
    AND m3.meta_key = '_billing_company'
    AND m4.meta_key = '_billing_first_name'
    AND m5.meta_key = '_billing_last_name'
ORDER BY p.post_date DESC

表: dawp_posts

ID post_name post_date post_status ...
1 Hello 2020-03-03 open ...
2 World 2021-01-01 open ...

dawp_postmeta

post_id meta_key meta_value
1 _order_currency CHF
1 _billing_first_name Daniel
1 _order_total 10
1 _billing_last_name Boxero
1 _billing_company Nonero Gmbh
2 _order_currency CHF
2 _billing_first_name Markus
2 _order_total 50
2 _billing_last_name Nachinzki

【问题讨论】:

【参考方案1】:

使用LEFT JOIN 时,除第一个表之外的所有条件都应在ON 子句中:

FROM `dawp_posts` `posts` LEFT JOIN
     `dawp_postmeta` `m1`
     ON `posts`.`ID` = `m1`.`post_id` AND `m1`.`meta_key` = '_order_total' LEFT JOIN
     `dawp_postmeta` `m2`
     ON `posts`.`ID` = `m2`.`post_id` AND `m2`.`meta_key` = '_order_currency' LEFT JOIN
     `dawp_postmeta` `m3`
     ON `posts`.`ID` = `m3`.`post_id` AND `m3`.`meta_key` = '_billing_company' LEFT JOIN
     `dawp_postmeta` `m4`
     ON `posts`.`ID` = `m4`.`post_id` AND `m4`.`meta_key` = '_billing_first_name' LEFT JOIN
     `dawp_postmeta` `m5`
     ON `posts`.`ID` = `m5`.`post_id` AND `m5`.`meta_key` = '_billing_last_name'
WHERE `posts`.`post_type` = 'shop_order' AND
      `posts`.`post_status` NOT LIKE 'wc-completed' ;

我还建议使用更有意义的表别名,例如motmocmbc——这是表含义的缩写。

【讨论】:

【参考方案2】:

FWIW,虽然它对性能没有任何帮助,但我发现这更容易阅读......

SELECT p.post_date
     , p.ID
     , MAX(CASE WHEN m.meta_key = '_order_total'        THEN meta_value END) order_total
     , MAX(CASE WHEN m.meta_key = '_order_currency'     THEN meta_value END) currency
     , MAX(CASE WHEN m.meta_key = '_billing_company'    THEN meta_value END) _billing_company
     , MAX(CASE WHEN m.meta_key = '_billing_first_name' THEN meta_value END) _billing_first_name
     , MAX(CASE WHEN m.meta_key = '_billing_last_name'  THEN meta_value END) _billing_last_name
  FROM dawp_posts p
  LEFT
  JOIN dawp_postmeta m
    ON m.post_id = p.ID
 WHERE p.post_type = 'shop_order' 
   AND p.post_status NOT LIKE 'wc-completed' 
 GROUP 
    BY p.post_date
     , p.id
 ORDER 
    BY p.post_date DESC

【讨论】:

为避免第二次排序,请更改为ORDER BY p.post_date DESC, p.id DESC

以上是关于Sql Left Join if Where 不存在的主要内容,如果未能解决你的问题,请参考以下文章

解析sql语句中left_joininner_join中的on与where的区别

sql语句中left join和inner join中的on与where的区别分析

关于 LEFT JOIN SQL 查询的 WHERE 帮助

SQL - LEFT JOIN 和 WHERE 语句仅显示第一行

SQL: LEFT JOIN , RIGHT JOIN , INNER JOIN 区别 , on 和 where条件的区别

浅谈!SQL语句中LEFT JOIN ON WHERE和LEFT JOIN ON AND的区别