一行中多个表的值

发布于 2024-07-27 17:44:35 字数 526 浏览 3 评论 0原文

我有以下 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 为 true,我希望它显示 table2 的字段名称,其中 table2.id = table3.id,但如果为 false,我需要它读取 table1 的名称字段的名称,其中 table1.id = table3.id。

显示结果的程序是一个桌面应用程序,我可以使用一些过程或其他东西来显示结果,但如果我有一个 SQL 查询来为我执行此操作,那就更好了。

I have the following 3 tables

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

Now I need a query on table3 that has to do the following:

To display the name field of table1 and table2. But my problem is that
if field P on table3 is true I want it to display the name of table2's field where table2.id = table3.id but if it is false I need it to read the name of table1's name field where table1.id = table3.id.

The program which will display the results is a desktop application and i could do it with some procedure or something to display them, but would be nicer if I had a SQL query to do this for me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

情栀口红 2024-08-03 17:44:35

这个:

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

更新:

如果大多数字段都为 false,则以下查询可能是最好的:

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 中是这样)。

This:

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

, or this:

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

In systems capable of doing HASH JOIN (that is Oracle, SQL Server, PostgreSQL, but not MySQL), the second one is better if the boolean values are distributed evenly, i. e. there are lots of both TRUE's and FALSE's, and if table3 is quite large.

The first one is better if there is a skew in distribution, if there are much fewer rows in table3 then in table1 or table2, or if you are using MySQL.

Update:

If the majority of fields are false, the following query will probably be the best:

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

Subquery here will only be used as a fallback, and will be executed only for the rare TRUE values.

Update 2:

I can't check it on Firebird, but on most systems the ORDER BY syntax as in query above will work. If it does not, wrap the query into an inline view:

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

, though it may hamper performance (at least in MySQL it does).

梦里°也失望 2024-08-03 17:44:35

您可以使用

select if(P, t1.name, t2.name) ...

you can use

select if(P, t1.name, t2.name) ...
逐鹿 2024-08-03 17:44:35
SELECT `id`, IF(`table3`.`P`, `table2`.`name`, `table1`.`name`) AS `name`
FROM `table3`
JOIN `table2` USING (`id`)
JOIN `table1` USING (`id`)
SELECT `id`, IF(`table3`.`P`, `table2`.`name`, `table1`.`name`) AS `name`
FROM `table3`
JOIN `table2` USING (`id`)
JOIN `table1` USING (`id`)
二智少女猫性小仙女 2024-08-03 17:44:35

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

考虑将表 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 万行被视为配置表:-)对于您正在处理的那种桌子来说,它可能不是必需的,但它是一个有用的工具。

Possibly not an option but sometimes a schema redesign will solve a lot of problems. Any solution that executes per-row functions should be examined very carefully for performance problems (actually any query should be continuously monitored for performance problems but especially per-row function ones).

Consider combining tables 1 and 2 together thus:

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              |

Then your query becomes a relatively simple (and almost certainly blindingly fast):

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

The performance issue usually only rears its head for large tables, mainframe sizes where 5 million rows is considered a configuration table :-) It may not be necessary for the sort of tables you're dealing with but it's a useful tool to have in the armory.

溺ぐ爱和你が 2024-08-03 17:44:35

就像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

It's as simple as this query in 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文