【问题标题】:Sql Join 2 tables get multiple column data referencing data in another tableSql Join 2表获取多列数据引用另一个表中的数据
【发布时间】:2021-10-17 17:45:19
【问题描述】:

我有两张桌子:

Games tbl                       Official tbl
Id    Ref1   Ref2   Ref3       RefId        Name
------------------------       ---------------------
1      1      3      2           1           Jaz
2      2      1      3           2           Rog
3      1      2      3           3           Dan

如果选择了一款游戏,我需要获取 Ref Names 作为该游戏的单独条目,例如:

Game 1 - Ref1 = Jaz         Game 2 - Ref1 = Rog
         Ref2 = Dan                  Ref2 = Jaz
         Ref3 = Rog                  Ref3 = Dan

我试过下面的sql,但似乎只能得到Ref1,而不是Ref2或Ref3:

Select a.Ref1, a.Ref2, a.Ref3 
From Games a 
Inner Join Official b On a.Ref1 = b.RefId 
Where a.Id = @Id

【问题讨论】:

    标签: sql sql-server tsql join


    【解决方案1】:

    您必须将Games 加入3 份Official

    SELECT g.Id,
           o1.Name Name1,
           o2.Name Name2,
           o3.Name Name3
    FROM Games g
    INNER JOIN Official o1 ON g.Ref1 = o1.RefId
    INNER JOIN Official o2 ON g.Ref2 = o2.RefId
    INNER JOIN Official o3 ON g.Ref3 = o3.RefId
    WHERE g.Id = ?;
    

    请参阅demo

    此外,您可以测试相关子查询而不是连接。
    有时它们会提供更好的性能:

    SELECT g.Id,
           (SELECT o.Name FROM Official o WHERE o.RefId = g.Ref1) Name1,
           (SELECT o.Name FROM Official o WHERE o.RefId = g.Ref2) Name2,
           (SELECT o.Name FROM Official o WHERE o.RefId = g.Ref3) Name3
    FROM Games g
    WHERE g.Id = ?;
    

    【讨论】:

    • 完美。谢谢。我以为我之前尝试过,但它没有用,但你的答案是正确的。
    • @mlg 很好,如果它有效。另外,在我编辑的答案中测试相关的子查询。不是那么优雅,但它们可能更适合大型数据集的性能。
    • 我一定会以另一种方式检查。再次感谢!
    【解决方案2】:

    您应该加入查询中官方表中的每个引用

      Select Ref1, a.Ref2, a.Ref3 From Games a 
        Left Join Official 
           b On a.Ref1 = b.RefId 
           OR a.Ref2 = b.RefId 
           OR a.Ref3 = b.RefId 
        Where a.Id = @Id
    

    【讨论】:

    • 要求是从Official而不是RefX获取名称。
    【解决方案3】:

    最初通过查看您想要的结果以及单个行上的名称,您似乎想要unpivot数据,使用cross apply 的以下查询将适用:

    select g.id GameId, o.refId, o.Name
    from games g
    cross apply (values (ref1,1), (ref2,2), (ref3,3))r(refId,seq)
    join officials o on o.refId=r.RefId
    where g.id=1
    order by r.seq;
    

    但是,您似乎希望每场比赛有一行三列,在这种情况下同样适用,现在也有 pivot 操作。

    与更简单的多连接选项相比,您可能认为这是冗长的,但是对于特定的 GameId,它只需要读取每个表一次

    select GameId, 
        Max(case when seq=1 then name end) Ref1,
        Max(case when seq=2 then name end) Ref2,
        Max(case when seq=3 then name end) Ref3
    from (
        select g.id GameId, o.refId, o.Name, r.Seq
        from games g
        cross apply (values (ref1,1), (ref2,2), (ref3,3))r(refId,seq)
        join officials o on o.refId=r.RefId
        where g.id=1
    )g
    group by GameId;
    

    working example Fiddle

    【讨论】:

      猜你喜欢
      • 2018-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-14
      • 2019-05-02
      • 2016-07-22
      相关资源
      最近更新 更多