【问题标题】:MySQL if/conditional query?MySQL if/条件查询?
【发布时间】:2014-02-15 02:57:03
【问题描述】:

假设我有一个包含以下列的成员资格表:

id, first, last, email, type, expires, parentid

类型可以是“父”或“子”

如果我查询一个孩子的 id,我如何返回孩子信息的名称和父母的到期/姓名?

基本上是这样的:

select 
  first, 
  last, 
  email, 
  if (type = "child"
      select 
      expires, 
      first as parent_first, 
      last as parent_last 
    from members 
    where id = parentid) 
  else ( expires ) 
  from members where id = 100

【问题讨论】:

    标签: mysql select join subquery


    【解决方案1】:

    不要从基于type = 'child'动态构造SQL的角度来看待它。相反,SQL 对相关集进行操作,因此解决方案实际上是 LEFT JOIN 将表与自身相对,以便始终返回父级(尽管有时可能为空)。

    虽然可以使用带有子选择的CASE 来交替返回父级或子级expires,因为您还需要父级的名称列,解决方案是总是返回它们即使他们可能是NULL

    SELECT
      c.first AS first,
      c.last AS last,
      c.email AS email,
      c.expires AS expires,
      /* parent fields will be NULL if child parentid is NULL */
      p.first AS parent_first,
      p.last AS parent_last,
      p.expires AS parent_expires
    FROM
      members c
      /* join against the same table matching 
         parentid of the child to id of the parent */
      LEFT JOIN members p ON c.parentid = p.id
    WHERE 
      c.id = 100
    

    使用了LEFT JOIN - 因此如果子列没有parentid 的值,则父列将返回NULL。如果您只想返回 expires 的一个值,您可以使用 COALESCE() 来选择父级的值,如果父级为 null,则返回子级:

    SELECT
      ...
      COALESCE(p.expires, c.expires) AS expires,
    

    或者使用CASE 并检查孩子的type(虽然COALESCE() 更好):

    SELECT
      ...
      CASE WHEN c.type = 'child' THEN p.expires ELSE c.expires END AS expires
    

    【讨论】:

    • 有趣。从事物的编码方面来看,获取可能未设置的东西的值可能会自找麻烦(比如查询不存在的列)......所以这肯定可以解释为什么我从来没有朝那个方向看。但这将要求我在演示方面“如果!过期则 parent_expires”,我希望通过始终使用“过期”来避免这种情况。感谢您的回复和解释! :)
    • @Ahhk 不,您不需要在演示端执行“if !expires then parent_expires”。这就是上面的COALESCE() 为您处理的。如果存在则返回父级过期,否则子级过期(假定没有父级)
    • 啊!现在一切都开始变得有意义了:) 再次感谢。
    猜你喜欢
    • 2013-10-11
    • 2016-06-08
    • 2012-02-02
    • 1970-01-01
    • 2016-11-06
    • 2016-02-07
    • 2018-12-24
    • 2012-04-05
    相关资源
    最近更新 更多