2014-09-25 132 views
0
Table A      Table B 
ID  Name     ID  Name Last_Name 
1  John     1  John Depp 
2  Henry     2  David Henry 
3  Ken 

我尝试在这些条件语句来选择名称:与内Select语句加入

  1. 如果NAMETableA能够与TableBNAME地图,然后选择Last_Name
  2. 如果NAMETableA等于LAST_NAMETableB中,则从TableA中选择NAME
  3. 如果NAMETableA不能与TableBNAMELAST_NAME地图,然后从TableA选择NAME

方法我用:

SELECT * FROM 
(SELECT A.ID NO, LAST_NAME REALNAME 
FROM TABLEA A 
INNER JOIN TABLEB B 
ON A.NAME = B.NAME 
    UNION ALL 
SELECT A.ID NO, A.NAME REALNAME 
FROM TABLEA A 
WHERE EXISTS (SELECT 1 FROM TABLEB B WHERE A.NAME = B.LAST_NAME) 
    UNION ALL 
SELECT A.ID NO, A.NAME REALNAME 
FROM TABLEA A 
WHERE NOT EXISTS (SELECT 1 FROM TABLEB B WHERE A.NAME = B.NAME OR A.NAME = B.LAST_NAME) 
)AS T 

问题:是,任何更简化查询我可以用它来实现的条件是什么?

+0

两者之间的ID是否可靠相关? – 2014-09-25 02:21:41

回答

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 
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 
+0

请注意,如果'last_name'在'tableb'中不是唯一的,则此语句中的第二个'SELECT'可以返回比原始查询多*的行。 – spencer7593 2014-09-25 02:38:48

+0

@ spencer7593 true,所以我只是添加了一个独特的地址 – 2014-09-25 02:44:57

+0

@BrianDeMilla:只要'(id,name)'元组在TABLEA中是唯一的,那么添加'DISTINCT'关键字就可以很好地解决这个问题。 (规范模式是对'id'的唯一约束,并且样本数据没有显示任何重复。我们注意到我们没有给出明确的保证'(id,name)'是唯一的。) – spencer7593 2014-09-25 02:48:04

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更清晰。)