【问题标题】:Join two tables containing two foreign keys连接两个包含两个外键的表
【发布时间】:2012-06-26 22:41:10
【问题描述】:

在编写 SQL 方面,我非常业余,所以也许这对某人来说是一件容易的事? 我有两个表如下:

表 1 - 设备名称、设备 ID、备用 ID

  • MyPhone,333,AAA
  • 她的电话,444,CCC

表 2 - 电话 ID、程序名称

  • 333,愤怒的小鸟
  • CCC、印象笔记

如您所见,Table2 使用 Table1 中的两种不同的 PhoneID 类型(DeviceID 和 AlternateID)。我正在寻找一个 sql 语句,它将导致如下输出:

  • 我的手机,愤怒的小鸟
  • 她的手机、印象笔记

感谢任何帮助。

干杯, 标记

【问题讨论】:

标签: sql join foreign-keys


【解决方案1】:
SELECT deviceName, programName
FROM table2 t2
JOIN table1 t1
 ON(t1.DeviceID=t2.PhoneID OR t1.AlternateID=t2.PhoneID)

或(可读性较差但更短)

SELECT deviceName, programName
FROM table2 t2
JOIN table1 t1
 ON(t2.PhoneID IN (t1.DeviceID, t1.AlternateID))

不过,如果 DeviceID 和 AlternateID 来自同一个集合,您应该考虑重构数据库:如果一个设备可以有多个有效 ID,而不仅仅是两个呢?

【讨论】:

  • 完美。非常感谢您的及时回复。干杯,马克。
  • 如果给定行的 DeviceID 和 AlternateID 都在表 2 中定义了怎么办?这将导致 2 行。这是OP想要的吗?不能确定。
【解决方案2】:

如果表 2 中同时定义了 333 和 AAA 怎么办?我假设您只希望每个 DeviceName 返回一行,这意味着您需要使用外连接两次加入表 2:

select DeviceName, 
       t2a.ProgramName, 
       t2b.ProgramName as AltProgramName
  from table1 t1
  left outer join table2 t2a
    on t1.DeviceID = t2a.PhoneID
  left outer join table2 t2b
    on t1.AlternateID = t2b.PhoneID

如果您只想列出一个 ProgramName,并且可以确定在两者都存在的情况下使用的优先级,您可以执行以下操作:(假设 DeviceID 胜过 AlternateID)

select DeviceName, 
       coalesce(t2a.ProgramName, t2b.ProgramName) as AltProgramName
  from table1 t1
  left outer join table2 t2a
    on t1.DeviceID = t2a.PhoneID
  left outer join table2 t2b
    on t1.AlternateID = t2b.PhoneID

如果您希望程序的第 1 列始终包含一个值,并且如果两者都存在,则仅在第 2 列中列出一个值,那么

select DeviceName, 
       coalesce(t2a.ProgramName, t2b.ProgramName) as ProgramName1,
       case when t2a.ProgramName is not null then t2b.ProgramName end as ProgramName2
  from table1 t1
  left outer join table2 t2a
    on t1.DeviceID = t2a.PhoneID
  left outer join table2 t2b
    on t1.AlternateID = t2b.PhoneID


编辑

我假设查询被用于报告目的,在这种情况下,您很可能只需要每个设备一行。

我刚刚意识到为什么 OP 可能希望每个设备返回多行。如果查询用于定义按任一名称查找设备的视图,则需要多行。

Jan's answer 非常适合查找视图。但是,根据数据库引擎的查询优化器和表的大小,它的性能可能好也可能不好。如果表非常大,那么您将需要索引查找。带有 OR 条件的连接可能会阻止某些系统上的索引查找。使用 UNION ALL 的等效查询可能支持更多系统上的索引查找。

select DeviceName,
       ProgramName
  from table1 t1
  join table2 t2
    on t1.DeviceID = t2.PhoneID
union all
select DeviceName,
       ProgramName
  from table1 t1
  join table2 t2
    on t1.AlternateID = t2.PhoneID

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-08
    • 1970-01-01
    • 2017-01-23
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多