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

现在我需要对 table3 进行查询,该查询必须执行以下操作:

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

显示结果的程序是一个桌面应用程序,我可以用一些程序或其他东西来显示它们,但如果我有一个 SQL 查询来为我做这件事会更好。

4

5 回答 5

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(即Oracle, SQL Server, PostgreSQL, 但不是),如果布尔值均匀分布,则第二个更好,即' 和'MySQL都有很多,并且 if非常大。TRUEFALSEtable3

如果分布存在偏差,如果table3table1or中的行数少得多table2,或者如果您正在使用 ,则第一个更好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:

我无法在 Firebird 上检查它,但在大多数系统上,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它确实如此)。

于 2009-07-17T12:24:13.093 回答
1

您可以使用

select if(P, t1.name, t2.name) ...
于 2009-07-17T12:24:35.480 回答
0
SELECT `id`, IF(`table3`.`P`, `table2`.`name`, `table1`.`name`) AS `name`
FROM `table3`
JOIN `table2` USING (`id`)
JOIN `table1` USING (`id`)
于 2009-07-17T12:25:57.227 回答
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 万行被视为配置表 :-) 对于您正在处理的表类型可能没有必要,但它是一个有用的工具军械库。

于 2009-07-17T12:39:20.990 回答
0

就像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
于 2017-11-24T12:09:55.277 回答