2009-07-17 71 views
2

我有以下3个表价值观上的行

Table1 

ID | NAME 
----------- 
1 | X 
2 | Y 
3 | Z 


Table2 

ID | NAME 
----------- 
1 | A 
2 | B 
3 | C 

Table3 
ID | P (Boolean field) | Other cols 
1 | True ... 
2 | True.... 
1 | False 

现在我需要有做以下的表3的查询:

要显示的表1和表2的名称字段。但我的问题是 如果table3上的字段P为真我希望它显示table2的字段的名称,其中table2.id = table3.id,但如果它是假的,我需要它读取table1的名称字段的名称where table1。 id = table3.id。

将显示结果的程序是一个桌面应用程序,我可以用一些程序或某些东西来显示它们,但如果我有一个SQL查询为我执行此操作会更好。

回答

3

此:

SELECT CASE WHEN p 
     THEN 
     (
     SELECT name 
     FROM table2 t2 
     WHERE t2.id = t3.id 
     ) 
     ELSE 
     (
     SELECT name 
     FROM table1 t1 
     WHERE t1.id = t3.id 
     ) 
     END 
FROM table3 t3 

,或者这样的:

SELECT CASE WHEN p THEN t2.name ELSE t1.name END 
FROM table3 t3 
JOIN table1 t1 
ON  t1.id = t3.id 
JOIN table1 t2 
ON  t2.id = t3.id 

在能够这样做HASH JOIN(即OracleSQL ServerPostgreSQL,但不是MySQL)的系统中,第二个是,如果更好布尔值均匀分布,即。即有很多TRUEFALSE,如果table3是相当大的。

第一个是更好,如果有在分布的偏斜,如果在table3少了许多行再table1table2,或者如果您正在使用MySQL

更新:

如果大部分领域都是假的,下面的查询可能会是最好的:

SELECT CASE WHEN p THEN 
     (
     SELECT name 
     FROM table2 t2 
     WHERE t2.id = t3.id 
     ) 
     ELSE t1.name 
     END AS cname 
FROM table3 t3 
JOIN table1 t1 
ON  t1.id = t3.id 
ORDER BY 
     cname 

子查询,这里将只被用来作为后备,并且将执行仅适用于罕见的TRUE值。

更新2:

我不能检查它的火鸟,但在大多数系统上ORDER BY语法查询上面会工作。如果没有,敷查询转换成一个内联视图:

SELECT cname 
FROM (
     SELECT CASE WHEN p THEN 
       (
       SELECT name 
       FROM table2 t2 
       WHERE t2.id = t3.id 
       ) 
       ELSE t1.name 
       END AS cname 
     FROM table3 t3 
     JOIN table1 t1 
     ON  t1.id = t3.id 
     ) q 
ORDER BY 
     cname 

,虽然它可能妨碍性能(至少在MySQL它)。

+0

大部分将具有场假,这样看来,第一个将适合我更好 – zz1433 2009-07-17 12:30:28

+0

然后,您可以用`table2`加入(这名假值),并在子查询的使用`table1`一个后备。 – Quassnoi 2009-07-17 12:37:38

1

可以使用

select if(P, t1.name, t2.name) ... 
0
SELECT `id`, IF(`table3`.`P`, `table2`.`name`, `table1`.`name`) AS `name` 
FROM `table3` 
JOIN `table2` USING (`id`) 
JOIN `table1` USING (`id`) 
0

可能不是一种选择,但有时架构的重新设计将解决很多问题。执行每行函数的任何解决方案应仔细检查非常性能问题(实际上任何查询应持续监视性能问题,尤其是每行功能的问题)。

考虑因而结合表1和表2一起:

Table1And2: 
    Id | IsTable2 | Name 
    ---+----------+----- 
    1 | false | X 
    2 | false | Y 
    3 | false | Z 
    1 | true  | A 
    2 | true  | B 
    3 | true  | C 
    Primary key (Id,IsTable2) 
    Possible index on (IsTable2) as well, depending on DBMS. 

Table3: 
    Id | P (Boolean field) | OtherCols 
    ---+--------------------+---------- 
    1 | true    | 
    2 | true    | 
    1 | false    | 

然后将查询变得相对简单(而且几乎可以肯定瞬息万变):

select a.Id, b.Name, a.OtherCols 
from Table3 a, Table1And2 b 
where a.Id = b.Id and a.P = b.isTable2 

性能问题通常只抬起了头对于大型表而言,其中500万行被认为是配置表的主机大小:-)对于您正在处理的那种表而言,它可能不是必需的,但它是在军械库中有用的工具。

1

这就像在mysql中的这个查询一样简单。

 SELECT T3.ID, 
       T3.P, 
       IF(T3.P = true, T2.NAME, T1.NAME) AS NAME 
     FROM Table3 T3 
     LEFT JOIN Table2 T2 ON T2.ID = T3.ID 
     LEFT JOIN Table1 T1 ON T1.ID = T3.ID