选择具有内部联接的语句

时间:2014-09-25 02:18:24

标签: mysql sql select inner-join

Table A                      Table B
ID     Name                  ID     Name    Last_Name
1      John                  1      John    Depp
2      Henry                 2      David   Henry
3      Ken

我试图在具有以下条件的声明中选择名称:

  1. 如果NAME中的TableA能够与NAME中的TableB进行映射,请选择Last_Name
  2. 如果NAME TableA等于LAST_NAME中的TableB,请从NAME
  3. 中选择TableA
  4. 如果NAME中的TableA无法使用TableB的{​​{1}}或NAME进行映射,请从{{{{}}中选择LAST_NAME 1}}。
  5. 我使用的方法:

    NAME

    问题:我可以使用更简化的查询来达到条件吗?

3 个答案:

答案 0 :(得分:2)

您可以使用CASE来提高可读性

SELECT A.ID NO, CASE WHEN A.Name = B.Name THEN B.LAST_NAME 
                     WHEN A.Name = B.LAST_NAME THEN A.NAME 
                     WHEN A.Name = B.Name AND A.Name = B.LAST_NAME THEN A.NAME  END AS REALNAME
FROM TABLEA A, TABLEB B

答案 1 :(得分:0)

您可以使用内部和外部联接而不是存在而不存在子查询,这可能会表现得更好:

select a.id, b.last_name as realname
  from tablea a
  join tableb b
    on a.name = b.name
union all
select distinct a.id, a.name
  from tablea a
  join tableb b
    on a.name = b.last_name
union all
select a.id, a.name
  from tablea a
  left join tableb b
    on a.name = b.name
    or a.name = b.last_name
 where b.name is null

答案 2 :(得分:0)

是的,您可以通过格式化使您的声明“更清晰”。如果您避免重复使用相同的表别名(也使EXPLAIN输出更容易与statemnt相关),那么人类读者也会更清楚。另外,如果对表别名和列名使用小写,则限定所有列引用。此外,消除不必要的内联视图也会使语句更容易阅读。

这在功能上等同于您的原始陈述,但它更“清晰”

    SELECT a.id        AS `NO`
         , b.last_name AS `REALNAME`
      FROM TABLEA a
      JOIN TABLEB b
        ON a.name = b.name
     UNION ALL
    SELECT e.id        AS `NO`
         , e.name      AS `REALNAME`
      FROM TABLEA e
     WHERE EXISTS 
           (SELECT 1 FROM TABLEB f WHERE f.last_name = e.name)
     UNION ALL
    SELECT o.id        AS `NO`
         , o.name      AS `REALNAME`
      FROM TABLEA o
     WHERE NOT EXISTS 
           (SELECT 1 FROM TABLEB p WHERE o.name IN (p.name,p.last_name))

(我也更喜欢小写的表名;但你的系统可能会设置为使用区分大小写的表名。如果表的名称不那么模糊,那么它也会更清楚。)

最后一个SELECT中的NOT EXISTS谓词可以用反连接模式替换;至于那是否会“更清晰”...对于那些熟悉反连接模式和能够选择它的人来说,它可能是。对于没有经验的人,可能不是,NOT EXISTS更清楚。)