【问题标题】:Why joining same table twice on two different columns returns different column values?为什么在两个不同的列上两次加入同一个表会返回不同的列值?
【发布时间】:2017-01-21 15:43:55
【问题描述】:

我有一个不是我编写的存储过程。

我无法理解他们如何两次加入同一个表 tblUsers 并返回不同的列值:

select distinct 
    usr.Name_FirstLast AS AssignedTo,
    usr1.Name_FirstLast as AssignedBy 
from 
    dbo.tblNoteStore  nt_str
join 
    dbo.tblNoteEntities entit ON nt_str.ID = entit.NoteGUID
join
    dbo.tblNoteDiaries nt_dia ON nt_str.ID = nt_dia.NoteGUID
join
    dbo.tblNoteEntries entri on nt_str.ID = entri.NoteGUID
                             and nt_dia.EntryGUID = entri.ID 
                             and entit.NoteGUID = entri.NoteGUID
left join 
    dbo.tblNoteRecipients recip ON entri.ID = recip.EntryGUID
--this is where the same table used twice 
left join 
    dbo.tblUsers  usr ON recip.UserGUID = usr.UserGUID   -- returns AssignedTo column
left join
    dbo.tblUsers usr1 ON usr1.UserGuid = entri.UserGUID   -- returns AssignedBy column
where 
    usr.UserGUID = '55610B2F-1997-40C0-9F01-EED3ED2939F9'

结果是我需要的,但为什么会这样呢?

  • dbo.tblUsers 有主键 UserGUID
  • dbo.tblNoteEntries 有一个外键 UserGUID
  • dbo.tblNoteRecipients 有一个外键 UserGUID

另外,我是否必须使用JOIN 中的所有表格才能收到结果?

【问题讨论】:

  • 在左边的桌子上保持一致

标签: sql-server tsql join


【解决方案1】:

从清理语法开始,把同一张表放在左边

select distinct 
       usr.Name_FirstLast  AS AssignedTo 
     , usr1.Name_FirstLast as AssignedBy 
from tblNoteStore      nt_str
join tblNoteEntities   entit 
      ON entit.NoteGUID  = nt_str.ID  
join tblNoteDiaries  nt_dia 
      ON nt_dia.NoteGUID = nt_str.ID 
join tblNoteEntries    entri 
      on entri.NoteGUID = nt_str.ID 
     and entri.NoteGUID = entit.NoteGUID
     and entri.ID       = nt_dia.EntryGUID           
join tblNoteRecipients recip 
      ON recip.EntryGUID = entri.ID   
join tblUsers          usr 
      ON usr.UserGUID  = recip.UserGUID   -- returns AssignedTo column
join tblUsers          usr1 
      ON usr1.UserGuid = entri.UserGUID   -- returns AssignedBy column
where usr.UserGUID = '55610B2F-1997-40C0-9F01-EED3ED2939F9'  

这在很多层面上都很愚蠢

tblUsers 是 PK 绝对没有理由留下来加入它

usr.UserGUID = '55610B2F-1997-40C0-9F01-EED3ED2939F9' 正在杀死左连接

来自 加入 tblNoteEntities 实体 ON entit.NoteGUID = nt_str.ID

我们知道entit.NoteGUID = nt_str.ID
但你在重复

 join tblNoteEntries entri 
      on entri.NoteGUID = nt_str.ID 
     and entri.NoteGUID = entit.NoteGUID  

我能做到的最好的感觉

select distinct 
       usr.Name_FirstLast  AS AssignedTo 
     , usr1.Name_FirstLast as AssignedBy 
from tblNoteStore      nt_str
join tblNoteEntities   entit 
      ON entit.NoteGUID  = nt_str.ID  
join tblNoteDiaries    nt_dia 
      ON nt_dia.NoteGUID = nt_str.ID 
join tblNoteEntries    entri 
      on entri.NoteGUID  = nt_str.ID 
     and entri.ID        = nt_dia.EntryGUID           
join tblNoteRecipients recip 
      ON recip.EntryGUID = entri.ID   
join tblUsers          usr 
      ON usr.UserGUID  = recip.UserGUID   -- returns AssignedTo column
     and usr.UserGUID = '55610B2F-1997-40C0-9F01-EED3ED2939F9'
join tblUsers          usr1 
      ON usr1.UserGuid = entri.UserGUID   -- returns AssignedBy column

【讨论】:

  • #Paparazzi 非常感谢。我想我终于明白了。谢谢
  • #狗仔队。我很惊讶你是如何破解这个 JOIN 的。我知道连接如何区分和工作,但那些复杂的连接让我感到困惑。你有什么经验法则吗?如何理解这个逻辑?就像你所说的“把同一张桌子放在左边”是什么意思?谢谢
【解决方案2】:

因为用户表连接到两个不同的表。

left join 
    dbo.tblUsers  usr ON recip.UserGUID = usr.UserGUID

加入别名recip,代表dbo.tblNoteRecipients,其中

left join
    dbo.tblUsers usr1 ON usr1.UserGuid = entri.UserGUID

加入别名entri,代表dbo.tblNoteEntries

请注意,这两个别名是在之前的连接中声明的:

                         |
join                     V
    dbo.tblNoteEntries entri on nt_str.ID = entri.NoteGUID
                             and nt_dia.EntryGUID = entri.ID 
                             and entit.NoteGUID = entri.NoteGUID
left join 
    dbo.tblNoteRecipients recip ON entri.ID = recip.EntryGUID
                            ^
                            |

【讨论】:

    猜你喜欢
    • 2012-05-29
    • 2015-04-03
    • 1970-01-01
    • 1970-01-01
    • 2014-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-18
    相关资源
    最近更新 更多