【问题标题】:Join with CASE or other alternative (MySQL)加入 CASE 或其他替代方案 (MySQL)
【发布时间】:2016-08-10 13:34:04
【问题描述】:

我有 2 个表需要加入。 表一:

User |Country|
--------------
 a   |  NZ   |
 a   |  NZ   |
 a   |  HU   |
 a   |  IL   |
 a   |  AU   |
 a   |  AU   |
 a   |  RO   |
 a   |  NZ   |
 a   |  NZ   | 
 a   |  NZ   |
 a   |  GB   |
 a   |  GB   |

表 2:

   User  |Country| Payment
    ----------------------
     a   |   GB  |  20
     a   |   AU  |  20
     a   |       |  30

我想要得到的最终结果是这个:

User | Country | Payment
--------------
 a   |   NZ    |   30
 a   |   NZ    |   30
 a   |   HU    |   30
 a   |   IL    |   30
 a   |   AU    |   20
 a   |   AU    |   20
 a   |   RO    |   30
 a   |   NZ    |   30
 a   |   NZ    |   30
 a   |   NZ    |   30
 a   |   GB    |   20
 a   |   GB    |   20

结果中有两个条件:

1 - 如果两个表中的国家/地区相同,则给我相应的付款,即在这种情况下仅适用于 GB 和 AU。

2 - 如果表 2 中的国家为 NULL,则加入到所有其他国家的付款(GB 和 AU 除外)

这件事可以用 2 个左连接来完成,但是有没有办法用 1 来完成呢?像 CASE/IF 之类的东西。我查看了几个加入 CASE 的示例,但它对我不起作用。

谢谢。

【问题讨论】:

  • 对于第2点,为什么现在是30?在计算之前是否还有其他数据需要考虑。如果是,那么它在哪里以及如何计算它。

标签: mysql sql if-statement join case


【解决方案1】:

虽然我认为 2 outer joins 会更有效,因为您只想使用单个 join,但这里有一个使用子查询和 conditional aggregation 的选项:

select usr, country, coalesce(payment, defaultpayment) as payment
from (
    select t1.usr, t1.country, 
        max(case when t1.country = t2.country then payment end) payment,
        max(case when t2.country is null then payment end) defaultpayment
    from t1
       left join t2 on t1.usr = t2.usr 
    group by t1.usr, t1.country 
) t

【讨论】:

  • 非常感谢!! max(case...) 是完美的解决方案。
【解决方案2】:

这是你想要“默认”的地方。 left join 很方便,实际上是两个。第一个与国家完全匹配;第二个引入NULL 值。

select t1.*, coalesce(t2.payment, t2d.payment) as payment
from t1 left join
     t2 t2
     on t1.country = t2.country left join
     t2 t2d
     on t2d.country is null;

这是解决问题的最佳方法,因为它可以利用t2(country)上的索引。

还有其他方法;例如:

select t1.*
       (select t2.payment
        from t2
        where t2.country = t.country or t2.country is null
        order by (t2.country is not null) desc
       ) as payment
from t;

或者,您可以使用一个显式的join 和聚合。或者像这样麻烦的东西:

select t1.*, t2.payment
from t1 join
     t2
     on t1.country = t2.country
union all
select t1.*, t2.payment
from t1 join
     t2
     on t2.country is null
where t.country not in (select t2.country from t2 where t2.country is not null);

但是有两个left joins 的版本是最好的方法。

【讨论】:

    【解决方案3】:

    我的解决方案是这个:

    在 INSTR(a.geo, b.Code) 0

    上左加入国家 b

    所以只有当实例匹配时才可能加入。

    【讨论】:

      猜你喜欢
      • 2011-07-24
      • 1970-01-01
      • 2011-09-01
      • 2012-12-27
      • 2014-07-08
      • 1970-01-01
      • 2021-02-14
      • 2010-11-28
      • 2014-10-22
      相关资源
      最近更新 更多