【问题标题】:How to conditionally select which table and column on a per row basis?如何有条件地逐行选择哪个表和列?
【发布时间】:2012-08-27 18:40:19
【问题描述】:

在对“链接”表的查询返回的结果中,我还想添加一个额外的列,该列显示从JOIN 中选择的“显示名称”值,条件是每行的“toTable”值.此外,有时“DisplayName”值是列串联的结果。

我的问题是我该怎么做?

我可以编写单独的查询并与UNION ALL 组合,但我想知道是否有条件方法来做到这一点

“链接”表中的每个条目都描述了两个表(可能是 3 个或更多表)中的一对条目之间的链接。

链接表:

| LinkID | fromTable | fromID | toTable | toID |
|      1 |        A  |      1 |      B  |    1 |
|      2 |        A  |      1 |      C  |    2 |
|      3 |        B  |      1 |      C  |    1 |
|      4 |        C  |      1 |      A  |    1 |

我想要的查询结果: WHERE Links.fromTable = 'A' OR Links.fromTable = 'C' 例如

| LinkID | fromTable | fromID | toTable | toID | DisplayName      |
|      1 |        A  |      1 |      B  |    1 |  Some Title      |
|      2 |        A  |      1 |      C  |    2 |  Loud-Quack      |
|      4 |        C  |      1 |      A  |    1 |  Linus           |

3 个不同列的表格:

Table A:    
| ID  | Name  |
| 1   | Linus |

-

Table B:    
| ID  | Title      |
|  1  | some title |

-

Table C:    
| ID  | CategoryA | CategoryB |
| 1   |   Bark    |    Softly |
| 2   |   Quack   |    Loud   |

- 这就是我这样做的方式UNION ALL,这不是很灵活: 编辑:实际上我认为下面是错误的,我现在正在看这个:

SELECT Links.*, A.Name AS DisplayName
FROM Links 
JOIN A ON Links.toID = A.ID 
WHERE Links.fromType IN ('A') AND Links.toType IN ('B')

UNION ALL

SELECT Links.*, CONCAT(C.CategoryB,'-',C.CategoryA) AS DisplayName
FROM Links 
JOIN C ON Links.toID = C.ID 
WHERE Links.fromType IN ('A') AND Links.toType IN ('C')

【问题讨论】:

    标签: mysql sql join conditional


    【解决方案1】:

    好吧,使用您的示例查询,您可以这样做:

    SELECT Links.*, COALESCE(A.Name,CONCAT(C.CategoryB,'-',C.CategoryA)) AS DisplayName
    FROM Links 
    LEFT OUTER JOIN A ON Links.toID = A.ID 
        AND Links.fromType IN ('A') AND Links.toType IN ('B')
    LEFT OUTER JOIN C ON Links.toID = C.ID 
        AND Links.fromType IN ('A') AND Links.toType IN ('C')
    

    只要您始终从连接的表中获得最多一个匹配项(即,您没有两个具有相同 Links.fromType IN ...Links.toType IN ... 条件的 不同 连接),此方法就可以工作)。

    【讨论】:

    • 经过考虑,我认为在我的实际用例中,可能存在重复链接。否则这个答案是一个不错的选择。我必须查找 COALESCE:返回列表中的第一个非 NULL 值,如果没有非 NULL 值,则返回 NULL。 from http://dev.mysql.com/
    【解决方案2】:

    我认为你需要inline CASE 声明

    SELECT  a.*,
            CASE toTable
                WHEN 'A' THEN b.Name
                WHEN 'B' THEN c.Title
                WHEN 'C' THEN CONCAT(d.CategoryB , '-',d.CategoryA )
            END AS DisplayName
    FROM    `links` a
                LEFT JOIN tableA b
                    ON a.toID = b.ID
                LEFT JOIN tableB c
                    ON a.toID = c.ID
                LEFT JOIN tableC d
                    ON a.toID = d.ID
    WHERE   fromtable IN ('A', 'C')
    

    SQLFiddle Demo

    【讨论】:

    • 我已经用我的实际用例对此进行了测试,它很有魅力。
    • @johowie 我使用了left join,所以如果三个表上不存在ID,它仍然会存在,但在displayname 列上有NULL 值。为了整齐地格式化它,你可以使用COALESCE
    • 如果一个链接被重复,这会返回两个链接吗?换句话说,如果链接表的两行中的 fromType、fromID、toType、toID 相同?在我的实际链接表中,还有其他列,包括“linkType”列。两个项目可能使用不同的链接类型链接两次。
    • @johowie 是的。但是如果它们被重复,你想对它们做什么?忽略其他链接还是全部显示?
    • 我想将它们全部显示出来,这就是我使用您的答案时发生的情况。太棒了!
    猜你喜欢
    • 2021-07-07
    • 1970-01-01
    • 2012-10-24
    • 2019-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-23
    • 1970-01-01
    相关资源
    最近更新 更多