【问题标题】:select with several joins on the same table在同一个表上选择多个连接
【发布时间】:2014-09-18 09:53:02
【问题描述】:

我在做这项工作时遇到了问题:

我有这张桌子(物品):

ItemId   Name  
1        Test  
2        Foo  
3        Bar  
4        Etc
5        Some

每个项目都有几个链接到它的命令,在一个表 CommandItem 中:

CommandId   ItemId  
912         2
916         2
922         2
954         2
976         3
977         3
979         3
982         3
998         4
1001        4
1020        4
1035        4
1039        5
1041        5

我只想获得几种commandId,它们与存储在表中的“函数”命令相匹配:

CommandId   FunctionId
912         81
916         72
922         56
954         13
976         81
977         72
979         56
982         13
998         81
1001        72
1020        56
1035        13
1039        81
1041        72

我只想要 FunctionId 为 81、72 或 56 的 commandId。
假设他们的名字是:
81:黄色
72:棕色
56:黑色

编辑:在某些情况下,itemId 可能不存在某些命令。
例如,我们可以说 itemId 5 有一个黄色和棕色的命令,但没有黑色的命令。
在这种情况下,我仍然需要 itemId 5 出现在表中,黑色为“NULL”。

我想要的最终视图有这种形式:

 ItemId      Name   Yellow  Brown  Black
 1           Test   NULL    NULL   NULL
 2           Foo    912     916    922
 3           Bar    976     977    979
 4           Etc    998     1001   1020
 5           Some   1039    1041   NULL

我试着做这个:

select 
    i.itemid, 
    i.name,
    c1.CommandId as brown, 
    c2.CommandId as yellow,
    c3.CommandId as black
from item i
inner join commanditem ci 
    on i.itemid = ci.itemid 
inner join command c1 
    on ci.CommandId = c1.CommandId and c1.FonctionId = 81
left outer  join command c2 
    on ci.CommandId = c2.CommandId and c2.FonctionId = 72
left outer  join command c3
    on ci.CommandId = c3.commandId and c3.FonctionId = 56

我也尝试过使用内部连接,使用枢轴......但没有成功。

我希望我足够清楚,感谢您给我的任何帮助。

【问题讨论】:

    标签: sql join sql-server-2008-r2 sql-server-2012


    【解决方案1】:

    这对我有用:

    select
        i.itemid,
        i.name,
        c1.CommandId as brown,
        c2.CommandId as yellow,
        c3.CommandId as black
    from (items i left outer join (commanditem ci1 inner join command c1 on ci1.commandid = c1.commandid) on i.itemid = ci1.itemid
                  left outer join (commanditem ci2 inner join command c2 on ci2.commandid = c2.commandid) on i.itemid = ci2.itemid
                  left outer join (commanditem ci3 inner join command c3 on ci3.commandid = c3.commandid) on i.itemid = ci3.itemid)
    where
          (c1.functionid = 81 or c1.functionid is null)
      and (c2.functionid = 72 or c2.functionid is null)
      and (c3.functionid = 56 or c3.functionid is null)
    

    我在另一个 DBMS 上对其进行了测试,但由于它是标准 SQL,它也可能对您有用。 结果是:

    ┌─────────────┬──────────┬─────────────┬─────────────┬─────────────┐
    │itemid       │name      │brown        │yellow       │black        │
    ├─────────────┼──────────┼─────────────┼─────────────┼─────────────┤
    │            2│Foo       │          912│          916│          922│
    │            3│Bar       │          976│          977│          979│
    │            4│Etc       │          998│         1001│         1020│
    │            1│Test      │             │             │             │
    └─────────────┴──────────┴─────────────┴─────────────┴─────────────┘
    (4 rows)
    

    好的,我明白了。下一个查询似乎做对了:

    select
        i.itemid,
        i.name,
        c1.CommandId as brown,
        c2.CommandId as yellow,
        c3.CommandId as black
    from (items i left outer join (commanditem ci1 inner join command c1 on ci1.commandid = c1.commandid and c1.functionid = 81) on i.itemid = ci1.itemid
                  left outer join (commanditem ci2 inner join command c2 on ci2.commandid = c2.commandid and c2.functionid = 72) on i.itemid = ci2.itemid
                  left outer join (commanditem ci3 inner join command c3 on ci3.commandid = c3.commandid and c3.functionid = 56) on i.itemid = ci3.itemid)
    

    使用新数据,它会产生所需的结果:

    ┌─────────────┬──────────┬─────────────┬─────────────┬─────────────┐
    │itemid       │name      │brown        │yellow       │black        │
    ├─────────────┼──────────┼─────────────┼─────────────┼─────────────┤
    │            1│Test      │             │             │             │
    │            2│Foo       │          912│          916│          922│
    │            3│Bar       │          976│          977│          979│
    │            4│Etc       │          998│         1001│         1020│
    │            5│Some      │         1039│         1041│             │
    └─────────────┴──────────┴─────────────┴─────────────┴─────────────┘
    (5 rows)
    

    【讨论】:

    • 嗨,这很好用,但它只显示每个函数都存在的行。为什么在您使用外连接时会这样做?
    • 我实际上忘了说某些命令可能不存在于特定项目中,例如 itemid 2 只有棕色和黄色。我将编辑它
    • @Aeron 我更正了查询,但将原始查询留在了我的答案中。尝试理解为什么原始查询不起作用(在一般情况下)将是一个很好的练习。
    • 谢谢,这很好用。我只是不明白我怎么找不到答案:(
    • 嗯,其实很简单。在第一个查询中,commanditem 和 command 的有效组合可能会出现错误的 functionid。然后被 where 子句过滤掉。在第二个查询中,仅考虑具有有效 functionid 的组合。我承认这有点棘手。相信我,我不是外连接的忠实粉丝,至少不是一个以上的外连接。他们往往使查询非常难以理解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-13
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    相关资源
    最近更新 更多