【问题标题】:Joining to a table multiple times多次加入一个表
【发布时间】:2012-05-30 13:52:55
【问题描述】:

我有三个表:Account、Management 和 ManagementAccountLookup。

Account 表包含位置。管理表包含业务层次结构中每个级别的记录。 Management 表还包含一个值 (LevelID),该值指示记录位于层次结构中的哪个级别。ManagementAccountLookup 表是连接它们的查找表。

我在编写查询以获取所有帐户及其两个关联管理记录时遇到问题。

例如:一个帐户可能有 5 条或更多管理记录与之关联,但我只关心 levelID 为 Brand 或 Region 的两个特定管理。另外,我只希望一个帐户在结果网格中显示一次。

结果集应如下所示:

AccountID   Brand      Region
---------   --------   ------
account1    Wendys     East US
account2    McDonalds  West US

这似乎是一个简单的问题,但我无法确切地弄清楚如何获得该结果。我已经尝试过自联接、子查询以及我能想到的所有其他方法,但我似乎无法将结果放在一行中。

任何帮助将不胜感激。

*编辑: ManagementAccountLookup 有两个字段(AccountID、ManagementID)。这些是另外两个表的 PK。
管理层有一列 LevelID,您可以通过该列判断记录是品牌、地区、地区等...

品牌和地区将是管理表中的两个单独的行。我需要结果网格将它们放在同一行中。

【问题讨论】:

  • 也许您可以向我们展示表的架构。我们想帮助您,但我们不知道要加入哪些字段
  • 对不起,我应该这样做,我只是不想通过添加一堆不必要的数据使我的问题更加混乱。我进行了编辑以使其更容易理解表结构。感谢您的意见,我会记住以后的问题。

标签: sql sql-server-2008 tsql join


【解决方案1】:

您需要添加两次 ManagementAccountLookup/Management 组合才能在一行中获取信息。我已将LevelID 标准直接放入连接中,以便在需要时轻松过渡到左连接。

select Account.AccountID,
       m_brand.Name Brand,
       m_region.Name Region
  from Account
 inner join ManagementAccountLookup mal_brand
    on Account.AccountID = mal_brand.AccountID
 inner join Management m_brand
    on mal_brand.ManagementID = m_brand.ManagementID
   and m_brand.LevelID = @Insert_Management_Brand_Level_Here
 inner join ManagementAccountLookup mal_region
    on Account.AccountID = mal_region.AccountID
 inner join Management m_region
    on mal_region.ManagementID = m_region.ManagementID
   and m_region.LevelID = @Insert_Management_Region_Level_Here

编辑:如果您需要显示所有帐户,您可以在括号中使用左/内连接组合:

select Account.AccountID,
       m_brand.Name Brand,
       m_region.Name Region
  from Account
  left join 
  (
       ManagementAccountLookup mal_brand
       inner join Management m_brand
         on mal_brand.ManagementID = m_brand.ManagementID
        and m_brand.LevelID = @Insert_Management_Brand_Level_Here
 )
   on Account.AccountID = mal_brand.AccountID
 left join 
 (
       ManagementAccountLookup mal_region
       inner join Management m_region
          on mal_region.ManagementID = m_region.ManagementID
         and m_region.LevelID = @Insert_Management_Region_Level_Here
 )
    on Account.AccountID = mal_region.AccountID

为了使其更具可读性,您可以使用 CTE:

; with mal_level as (
  select AccountID,
         m.LevelID,
         m.Name
    from ManagementAccountLookup mal
   inner join Management m
      on mal.ManagementID = m.ManagementID
)
select Account.AccountID,
       m_brand.Name Brand,
       m_region.Name Region
  from Account
  left join mal_level m_brand
    on Account.AccountID = m_brand.AccountID
   and m_brand.LevelID = @Insert_Management_Brand_Level_Here
  left join mal_level m_region
    on Account.AccountID = m_region.AccountID
   and m_region.LevelID = @Insert_Management_Region_Level_Here

或outer apply:

select Account.AccountID,
       b.Brand,
       r.Region
  from Account
 outer apply
 (
       select m_brand.Name Brand
         from ManagementAccountLookup mal_brand
        inner join Management m_brand
           on mal_brand.ManagementID = m_brand.ManagementID
          and m_brand.LevelID = @Insert_Management_Brand_Level_Here
        where mal_brand.AccountID = Account.AccountID
 ) b
 outer apply
 (
       select m_region.Name Region
         from ManagementAccountLookup mal_region
        inner join Management m_region
           on mal_region.ManagementID = m_region.ManagementID
          and m_region.LevelID = @Insert_Management_Region_Level_Here
        where mal_region.AccountID = Account.AccountID
 ) r

【讨论】:

  • 太棒了!看起来它正在工作。明天我会做更多的测试来确定,但我认为这是我需要的。另外,感谢您对表结构的猜测,为我提供了相当多的复制和粘贴代码供我测试。我曾尝试过类似的事情,但我从那里加入了一次 ManagementAccountLookup 表和两次管理表。那是我被挂断的地方。
  • 我对这个声明还有另一个问题。如果我需要允许帐户显示在网格中,即使他们没有关联区域或品牌,我将如何处理?我不能只将连接更改为左连接,因为这会产生很多重复。我想出的唯一方法(这并不漂亮)是将结果联合到另一个查询中,关闭所有没有管理的帐户。有什么建议吗?
  • @Justin 抱歉耽搁了,我昨天下班了。请检查我的更新答案。
  • 非常感谢!我因为没有弄清楚我在第一个查询中遗漏的只是括号而感到自责。我昨天最终创建了一个视图,该视图基本完成了您的 CTE 所做的事情。我以前从未见过这样做,但我更喜欢它而不是我创建的视图。我之前也从未见过外部应用方法。非常感谢您的帮助,我从中学到了很多。 (另外,我对您的答案进行了轻微修改,因为如果不在括号后加上“作为某物”,申请将无法工作。显然,我的编辑必须在他们发布之前进行审核)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-23
  • 2021-04-01
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多