【问题标题】:MySql, return default value if no rows returnedMySql,如果没有返回行,则返回默认值
【发布时间】:2018-12-12 14:24:15
【问题描述】:

我有如下查询

SELECT cap_id FROM cap_master WHERE   
        (cap_type = 'Type1' AND cap_desc = 'CapDesc1') 
     OR (cap_type = 'Type2' AND cap_desc = 'CapDesc2')
     OR (cap_type = 'Type3' AND cap_desc = 'CapDesc3')
     OR (cap_type = 'Type4' AND cap_desc = 'CapDesc4')
order by cap_type,cap_desc

这会根据 where 条件返回多行,我正在寻找的是一个不返回任何行的条件,我应该有一个默认值,比如“0”。截至目前,我没有得到任何行。

例如,如果第 3 个条件 (cap_type = 'Type3' AND cap_desc = 'CapDesc3') 不匹配,我希望得到如下输出:

23
34
0  
45

我检查了给出的解决方案,例如

Return a value if no rows match

Return Default value if no row found -mysql

但似乎它们不适用于返回的多行。任何指针将不胜感激。

这里有一个Fiddle 可以玩。

【问题讨论】:

  • 如果您发布示例数据和预期结果会有所帮助,最好是作为 SQL Fiddle。
  • 如果您有一个包含所有可能类型的引用表,那么您可以通过cap_type 执行OUTER JOIN。所以你会知道缺少哪个类型
  • 在提问中添加了小提琴。
  • 是否有另一个表包含所有可能的类型? @pranav
  • 不,我们没有,这实际上是一个主表。

标签: mysql sql


【解决方案1】:

你想要一个left join

select coalesce(cm.cap_id, 0) as cap_id
from (select 'Type1' as cap_type, 'CapDesc1' as cap_desc union all
      select 'Type2' as cap_type, 'CapDesc2' as cap_desc union all
      select 'Type3' as cap_type, 'CapDesc3' as cap_desc union all
      select 'Type4' as cap_type, 'CapDesc4' as cap_desc
     ) c left join
     cap_master cm
     on cm.cap_type = c.cap_type and cm.cap_desc = c.cap_desc
order by c.cap_type, c.cap_desc;

如果您需要支持NULL cap_desc(这不是原始问题的一部分),您可以这样做:

select coalesce(cm.cap_id, 0) as cap_id
from (
      select 'Type5' as cap_type, null as cap_desc
     ) c left join
     cap_master cm
     on cm.cap_type = c.cap_type and 
        (cm.cap_desc = c.cap_desc or cm.cap_desc is null and c.cap_desc is null)
order by c.cap_type, c.cap_desc;

Here 是一个 SQL Fiddle。

【讨论】:

  • 我试过类似的,但这不会维持秩序。可以检查提供的小提琴。 sqlfiddle.com/#!9/4b9bb0/2
  • 我添加了一个似乎可以正常工作的解决方案。如果它会损害效率,总是欢迎更好、更有效的解决方案:)
  • @pranav 。 . .此查询似乎完全符合您的要求:sqlfiddle.com/#!9/8661c7/1
  • 感谢 Gordon,现在可以使用了。所以我们现在有两种方法可以做。我用 IFNULL 试过了,效果也很好。这个很简洁,会用这个。
  • 它给出了:'在我的数据库中操作'=''的排序规则(latin1_swedish_ci,IMPLICIT)和(utf8_general_ci,COERCIBLE)的非法混合。遇到这种情况的人可以按照此处给出的方法进行修复:stackoverflow.com/questions/1008287/…
【解决方案2】:

我能够弄清楚的解决方案。不确定这是否会严重影响效率,我想我一次最多会有 20 个条件。让我知道是否有其他选择。

SELECT ifnull((SELECT cap_id FROM cap_master WHERE cap_type = 'Type4' AND 
cap_desc = 'CapDesc4' ),0) as cap_id
union all
SELECT ifnull((SELECT cap_id FROM cap_master WHERE cap_type = 'Type7' AND 
cap_desc = 'CapDesc7' ),0) as cap_id
union all
SELECT ifnull((SELECT cap_id FROM cap_master WHERE cap_type = 'Type3' AND 
cap_desc = 'CapDesc3' ),0) as cap_id
union all
SELECT ifnull((SELECT cap_id FROM cap_master WHERE cap_type = 'Type6' AND 
cap_desc = 'CapDesc6' ),0) as cap_id

【讨论】:

    【解决方案3】:

    我会使用 IFNULL 来做你想做的事。它未经测试,因为您没有提供最少的数据集来运行查询:

    SELECT IFNULL( (SELECT cap_id FROM cap_master WHERE   
            (cap_type = 'Type1' AND cap_desc = 'CapDesc1`) 
         OR (cap_type = 'Type2' AND cap_desc = 'CapDesc2')
         OR (cap_type = 'Type3' AND cap_desc = 'CapDesc3')
         OR (cap_type = 'Type4' AND cap_desc = 'CapDesc4')
    order by cap_type,cap_desc) ,'0');
    

    Here你可以找到更多关于 IFNULL 的细节

    【讨论】:

    • 如果 没有 数据与 Type1Type2、Type3 AND Type4?仅当缺少特定类型(对于该结果行)时,他才需要0
    • 不,它应该完成它的工作(但我没有用 OP 的数据测试它)。如果这不起作用,唯一的其他选择是将查询拆分为 4 个子查询
    • 可以,但这是最不高效的方法
    • 尝试使用 IFNULL ,它似乎不适用于多行。给出“子查询返回超过 1 行”。
    • 所以我尝试了您的查询。它要么返回错误,因为返回的行不止一行,要么就像我说的那样 - 它只有在没有数据满足任何条件时才有效:sqlfiddle.com/#!9/d2a4a4/1/0
    【解决方案4】:

    尝试 CASE 函数 :) 您可以指定应该显示的内容和位置

    https://www.w3schools.com/sql/func_mysql_case.asp

    【讨论】:

    • CASE 在这里无济于事
    • 我认为 CASE 会在我们获得一排时有所帮助。这里就好像没有返回行写一个case就可以了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-25
    • 1970-01-01
    • 2018-08-23
    • 2013-05-12
    相关资源
    最近更新 更多