【问题标题】:SQL Select With Multiple References to Single Table对单个表的多个引用的 SQL 选择
【发布时间】:2010-08-10 18:24:30
【问题描述】:

我有一个包含多个关系表的 SQL 数据库。主表中有一些字段多次引用另一个表。例如,假设我有一个负责多个州销售的销售人员数据库。我的数据库有 State1、State2 和 State3 的字段,所有这些字段都映射回 States 表。我一生都无法弄清楚如何编写查询以返回具有所有枚举状态的记录。如果我只需要一个 State 字段,我知道我会这样做:

SELECT Master.Name, State.Enumeration AS 'State'
FROM MasterTable Master, StateTable State
WHERE Master.State1 = State.ID;

如何为我的所有 State 字段扩展它?

谢谢。

【问题讨论】:

    标签: sql database


    【解决方案1】:

    从每个唯一连接返回一列到状态:

    select m.Name, s1.Enumeration as State1, s2.Enumeration as State2, s3.Enumeration as State3
    from MasterTable m
    left join StateTable s1 on m.State1 = s1.ID
    left join StateTable s2 on m.State2 = s2.ID
    left join StateTable s3 on m.State3 = s3.ID
    

    从 3 个连接中返回所有状态的 1 列:

    select m.Name, ISNULL(s1.Enumeration + ',','') 
                   + ISNULL(s2.Enumeration + ',','') 
                   + ISNULL(s3.Enumeration,'') as Enumeration
    from MasterTable m
    left join StateTable s1 on m.State1 = s1.ID
    left join StateTable s2 on m.State2 = s2.ID
    left join StateTable s3 on m.State3 = s3.ID
    

    还有列查询...

    select m.Name,
     ISNULL((select Enumeration from StateTable where ID = m.State1),'') as State1,
     ISNULL((select Enumeration from StateTable where ID = m.State2),'') as State2,
     ISNULL((select Enumeration from StateTable where ID = m.State3),'') as State3
    from MasterTable m
    

    【讨论】:

    • @lumberjack4:您发布的 ANSI-89 语法与 Fosco 的 ANSI-92 在性能上没有区别。 ANSI-92 的好处是标准化和广泛支持的 OUTER JOIN(至少是左,右)语法。
    • 谢谢你们。。我在编辑添加第二个查询时意识到了这一点。
    • 子选择?我的眼睛,它们燃烧! =)
    • 哈哈哈 :) 他说他想避免“显式加入”,哈哈。我可以删除那个,我只是想彻底...
    【解决方案2】:

    您需要使用表别名来连接同一张表的多个副本:

       SELECT m.Name, 
              s1.Enumeration AS 'State1',
              s2.Enumeration AS 'State2'
         FROM MasterTable m
    LEFT JOIN StateTable s1 = s1.id = m.state1
    LEFT JOIN StateTable s2 = s1.id = m.state2
    

    INNER JOIN 要求数据存在 - 如果不存在,则排除整个记录。 LEFT JOIN 更安全,例如 state1/2/3/etc 允许 NULL...

    【讨论】:

    • 我希望避免显式连接,但它似乎必须这样做。
    • 我知道我的原始查询在幕后进行了联接,我想我只是对数据库不够熟悉,无法知道何时使用什么联接。
    • @lumberjack4:您一直在使用带有 ANSI-89 的 INNER 连接,而不是 OUTER 连接 - 这是视图的可视化演示:codinghorror.com/blog/2007/10/…
    • 良好的一般规则:左连接始终显示左(第一个)表中的所有记录。 Right Join 总是显示 RIGHT 表中的所有记录。 JOIN(又名 INNER JOIN)仅向您显示两个表中都有匹配记录的位置。 CROSS JOIN 向您显示两个表的乘积,并且使用频率较低。
    • @lumberjack4: 没关系.. 不过我们是。 :)
    【解决方案3】:

    select tbl_book_con1.city,con1,tbl_book_destination.city,destination,labar_char,tbl_book_c_from.city,c_from,tbl_book_c_to.city,c_to,tbl_book_payment.city,paymentid from tbl_booking tbb_bookinner join tbl_master tbl_book_con1 on tbl_book_con1.id = tbb_book.con1
    inner join tbl_master tbl_book_destination on tbl_book_destination.id = tbb_book.con1
    inner join tbl_master tbl_book_c_from on tbl_book_c_from.id = tbb_book.con1
    inner join tbl_master tbl_book_c_to on tbl_book_c_to.id = tbb_book.con1
    inner join tbl_master tbl_book_payment on tbl_book_payment.id = tbb_book.con1

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-25
      • 2011-07-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-07
      • 1970-01-01
      • 2018-02-07
      • 2011-02-01
      相关资源
      最近更新 更多