【问题标题】:Conditional Join 3 Tables - Difficulty specifying Which Table and Column to return条件连接 3 个表 - 难以指定要返回的表和列
【发布时间】:2020-02-22 03:03:41
【问题描述】:

在 SQL Server 中工作

我有 3 张桌子

[TESTDB].[dbo].[TestList]
[Routing].[dbo].[WUList]
[Routing].[dbo].[WUArea]

[TESTDB].[dbo].[TestList] 数据看起来像

TestID
1089
41651
1235
6987
51555
71666

[Routing].[dbo].[WUList] 数据看起来像

TestIDS    AreaPerson1   AreaPerson2    AreaPerson3
01089      TSmith        MBlevins       OMyhead
01099      RJohns        NULL           NULL
03368      RJohns        TPayne         MSmith
45646      TSmith        MBlevins       NULL
55566      NULL          MBlevins       WRestle
77788      ORandy        NULL           LOrdy
02347      MArt          TPayne         MSmith
03333      NULL          NULL           NULL 
04444      NULL          NULL           NULL

[Routing].[dbo].[WUArea] 数据看起来像

Area AreaPerson1   AreaPerson2    AreaPerson3
01   ORandy        MBlevins       OMyhead
03   RJohns        SNicks         IPfreely
04   RJohns        MBlevins       BFort
07   TSmith        SNicks         BFort
41   MArt          TSmith         WRestle
45   ORandy        ORandy         ORandy        
51   ...           ...            ...
52   ...           ...            ...
71   ...           ...            ...

我已经能够将 [TestList] 加入 [UWArea] 或 [WUList] 我需要的数据显示方式,但我无法以我需要的方式加入 3 个列表。

  1. 并非每个 TestID 都出现在 [WUList] 或 [WUArea] 中
  2. 如果 TestID 出现在 [UWList] 中,则并非每一列都包含一个值
  3. [WUList]中出现一些TestID,[WUList]中的每一列都包含NULL

最终目标

  1. 常见的联接字段为 [TestList].[TestID]、[WUList].[TestIDS] 和 [WUArea].[Area]

  2. 返回列 [TestID]、[AreaPerson1]、[AreaPerson2]、[AreaPerson3]

  3. 将[TestList]加入[WUList]时,如果有任何'persons'返回NULL,则将[TestID]的前两位数字加入[WUArea]。[Area]并获取对应的“人”

  4. **[TestList].[TestID] 为 4 位数字,在加入 [WUArea].[Area] 时,应在左第 1 位附加 0。 [TestID] 长度为五位,可以使用 LEFT 两位数连接

  5. 如果[TestList].[TestID]没有出现在[WUList]中或者[TestList].[TestID]的左2位没有出现在[WUArea]中,设置[AreaPerson1]=JDoe,[ AreaPerson2] = SDoe,[Areaperson3] = TBuck

这个让我夜不能寐。您的帮助将不胜感激。

【问题讨论】:

    标签: sql sql-server join conditional-statements


    【解决方案1】:
    create table TestList
    (
    TestID int
    )
    
    insert TestList
    values
    (1089)
    , (41651)
    , (1235)
    , (6987)
    , (51555)
    , (71666)
    , (01099)
    , (03368)
    , (45646)
    , (55566)
    , (77788)
    , (02347)
    , (03333)
    , (04444)
    
    create table WUList
    (
    TestIDS int,
    AreaPerson1 varchar(10)
    , AreaPerson2 varchar(10)
    , AreaPerson3 varchar(10)
    )
    
    insert WUList
    values
    ('01089','TSmith','MBlevins','OMyhead')
    , ('01099','RJohns',NULL,NULL)
    , ('03368','RJohns','TPayne','MSmith')
    , ('45646','TSmith','MBlevins',NULL)
    , ('55566',NULL,'MBlevins','WRestle')
    , ('77788','ORandy',NULL,'LOrdy')
    , ('02347','MArt','TPayne','MSmith')
    , ('03333',NULL,NULL,NULL)
    , ('04444',NULL,NULL,NULL)
    
    create table WUArea
    (
    Area varchar(3),
    AreaPerson1 varchar(10)
    , AreaPerson2 varchar(10)
    , AreaPerson3 varchar(10)
    )
    
    insert WUArea
    values
    ('01','ORandy','MBlevins','OMyhead')
    , ('03','RJohns','SNicks','IPfreely')
    , ('04','RJohns','MBlevins','BFort')
    , ('07','TSmith','SNicks','BFort')
    , ('41','MArt','TSmith','WRestle')
    , ('45','ORandy','ORandy','ORandy')
    
    select a.TestID
        , case
            when b.TestIDS is null or c.Area is null then 'JDoe'
            else ISNULL(b.AreaPerson1,c.AreaPerson1)
        end as AreaPerson1
        , case
            when b.TestIDS is null or c.Area is null then 'SDoe'
            else ISNULL(b.AreaPerson2,c.AreaPerson2)
        end as AreaPerson2
        , case
            when b.TestIDS is null or c.Area is null then 'TBuck'
            else ISNULL(b.AreaPerson3,c.AreaPerson3)
        end as AreaPerson3
    from TestList a
            left join WUList b on a.TestID = b.TestIDS
            left join WUArea c on '0' + LEFT(a.TestID,1) = c.Area
    

    请注意:您上面在 TestList 中的数据样本没有足够的相关数据,因此我将 WUList 表中的 TestIDS 添加到了 TestList 表中以供更多使用。

    我很快就把它搞定了,所以如果你的表数据集中有任何其他变化,那么你需要调整。到目前为止,它涵盖了您的所有基础(至少据我所知)

    如果您想在结果集中查看更多数据以验证是否考虑了 NULL,请使用以下语句。

    select a.TestID, '0' + LEFT(a.TestID,1) as WUAreaTestID
        , b.AreaPerson1
        , case
            when b.TestIDS is null or c.Area is null then 'JDoe'
            else ISNULL(b.AreaPerson1,c.AreaPerson1)
        end as AreaPerson1n
        , b.AreaPerson2
        , case
            when b.TestIDS is null or c.Area is null then 'SDoe'
            else ISNULL(b.AreaPerson2,c.AreaPerson2)
        end as AreaPerson2n
        , b.AreaPerson3
        , case
            when b.TestIDS is null or c.Area is null then 'TBuck'
            else ISNULL(b.AreaPerson3,c.AreaPerson3)
        end as AreaPerson3n
        , c.*
    from TestList a
            left join WUList b on a.TestID = b.TestIDS
            left join WUArea c on '0' + LEFT(a.TestID,1) = c.Area
    

    【讨论】:

    • 谢谢!这肯定比我设法得到的更接近。 [TESTDB].[dbo].[TestList] 实际上包含 2319 行数据。当我按 TestID 分组时,行数被压缩为 447 行,这是期望的结果。这个解决方案产生的报价比我预期的多几列
    • TestList 表只包含一个字段,对吧?那么您是说该表中有重复的值,其中当您按 TestID 分组时,它会压缩为 447?我不会在这件事上关注你。此外,最后的查询语句只产生 4 列:TestID、AreaPerson1、AreaPerson2、AreaPerson3。您是否正在运行我为数据校对提供的第二个查询而不是第一个查询?
    • 杜阿,你一针见血。我在测试时不小心运行了第二个查询而不是第一个查询。谢谢你!!! TestList 表包含多个列,但我只需要针对其他表查询第一列的值即可获得所需的结果。很抱歉省略了它。我调整了解决方案,以按语言包含所需的组,并且非常完美!!!!已标记答案。
    • 我超前了。似乎 left join WUArea c on '0' + LEFT(a.TestID,1) = c.Area 可能无法按预期工作。我发现在应该返回 c.[AreaPerson1] 或 person2 或 3 的情况下,而是返回 JDoe、SDoe 或 TBuck 的默认值
    • 您是说您上面的第 5 个最终目标是单独限定每个字段(AreaPerson1、AreaPerson2、AreaPerson3),而不是作为整个记录?我认为该目标会影响整个记录。例如:在上面的数据中,TestList.TestID 值 1235 与 WUList 表连接时没有结果(NULL),但在与 WUArea 表连接时确实有结果。您在目标 #5 中给出了“或”条件但是您的意思是对于 TestID 值 1235,查询应该从 WUArea 表返回 AreaPerson1、AreaPerson2 和 AreaPerson3,因为它匹配?
    猜你喜欢
    • 2019-12-21
    • 2017-03-17
    • 1970-01-01
    • 2014-06-04
    • 2014-03-31
    • 1970-01-01
    • 2012-04-05
    • 2012-02-12
    • 1970-01-01
    相关资源
    最近更新 更多