Sql server 如何将左连接与一组其他连接一起使用

Sql server 如何将左连接与一组其他连接一起使用,sql-server,Sql Server,我正在尝试基于EquipWorkOrderID连接两个表。表(设备工单和设备工单) 在下面的查询中,如果同一个ID有两个UserNm,它将根据ID复制行。如果ID匹配,我希望两个UserNm和Hrs处于相同的角色(如果可能) 我的结果现在给我的例子 EquipWorkOrderID/Equip/Description/Resolution/UserNm/Hrs --------------------------------------------------------- 1

我正在尝试基于EquipWorkOrderID连接两个表。表(设备工单和设备工单) 在下面的查询中,如果同一个ID有两个UserNm,它将根据ID复制行。如果ID匹配,我希望两个UserNm和Hrs处于相同的角色(如果可能)

我的结果现在给我的例子

EquipWorkOrderID/Equip/Description/Resolution/UserNm/Hrs
---------------------------------------------------------
1              / ForkLift / Bad   /Fixed/John Doe / 2
1              /Forklift / Bad    /Fixed/Jane Doe /2
我想看什么

EquipWorkOrderID/Equip/Description/Resolution/UserNm1/Hrs1/UserNm2/Hrs2
---------------------------------------------------------
1              / ForkLift / Bad   /Fixed/John Doe  / 2  / Jane Doe / 2

我已将您的查询结果放入一个表(
selection
)中,并在(
cte
)中从中检索数据。用查询替换CTE的内容,并添加我创建的两个新列(
UsrNum
HrsNum

我的解决方案使用一个double(一个用于
UserNm
列,另一个用于
Hrs
列),后跟一个分组。这可能并不理想,但它完成了任务

下面是一个示例,演示如何构建解决方案

样本数据

这只是重新创建当前查询的结果

create table selection
(
  EquipWorkOrderID int,
  Equip nvarchar(10),
  Description nvarchar(10),
  Resolution nvarchar(10),
  UserNm nvarchar(10),
  Hrs int
);

insert into selection (EquipWorkOrderID,Equip,Description,Resolution,UserNm,Hrs) values
(1, 'ForkLift', 'Bad', 'Fixed', 'John Doe', 2),
(1, 'Forklift', 'Bad', 'Fixed', 'Jane Doe', 2);
解决方案

用查询替换CTE的第一部分,并添加两个新列

with cte as
(
  select EquipWorkOrderID,Equip,Description,Resolution,UserNm,Hrs,
   'Usr' + convert(nvarchar(10),row_number() over(partition by Equip order by UserNm)) as 'UsrNum',
   'Hrs' + convert(nvarchar(10),row_number() over(partition by Equip order by UserNm)) as 'HrsNum'
  from selection
)
select ph.EquipWorkOrderId, ph.Equip, ph.Description, ph.Resolution,
       max(ph.Usr1) as 'UserNm1',
       max(ph.Hrs1) as 'Hrs1',
       max(ph.Usr2) as 'UserNm2',
       max(ph.Hrs2) as 'Hrs2'
from cte c
pivot (max(c.UserNm) for c.UsrNum in ([Usr1], [Usr2])) pu
pivot (max(pu.Hrs) for pu.HrsNum in ([Hrs1], [Hrs2])) ph
group by ph.EquipWorkOrderId, ph.Equip, ph.Description, ph.Resolution;
结果

结果是这样的
janedoe
UserNm1
,因为这就是新的
UserNum
列的构造方式(
orderbyusernm
)。如果您需要约翰·多伊保持第一,请按调整
顺序

EquipWorkOrderId  Equip     Description  Resolution  UserNm1   Hrs1  UserNm2  Hrs2
----------------- --------- ------------ ----------- --------- ----- -------- -----
1                 ForkLift  Bad          Fixed       Jane Doe  2     John Doe 2

编辑:与原始查询合并的解决方案(未测试)

编辑2:如何使用pivot

Select pivot_table.*
From
(
    Select  a.EquipWorkOrderID,
            b.Hrs,
            c.UserNm,
            'Tech' + convert(nvarchar(10), row_number() over(order by c.UserNm)) -- construct _generic_ names
    From EquipWorkOrder a
    Left Join EquipWorkOrderHrs b
        On a.EquipWorkOrderID = b.EquipWorkOrderID
    Left Join AppUser c
        On c.UserID = b.UserID
) t
/*
Pivot (Count(Hrs) For UserNm     IN ([Tech1], [Tech2], [Tech3], [Tech4], [Tech5])) AS pivot_table -- UserNm does not contain values like "Tech1" or "Tech2"
*/
Pivot (Count(Hrs) For GenUserNm  IN ([Tech1], [Tech2], [Tech3], [Tech4], [Tech5])) AS pivot_table -- pivot over the _generic_ names

你的标题问题有什么关系?你没有使用左连接。。。您使用的是旧式内部联接,不应再使用。您应该使用显式联接。我正在尝试找出如何将左联接与旧式内部联接或其他方式一起使用。将行值(John Doe、Jane Doe)转换为列(UserNm1、UserNm2)称为数据的“旋转”。语法和示例可以在中找到。@sander我查看了文档,但仍然不确定如何将其添加到当前查询中。添加了一个可能的答案,一定要看看它是如何工作的。尝试了解如何添加原始查询。每次添加时,它都会给我一个错误,并且不会运行查询。我将您的原始查询与我的解决方案合并。我没有对此进行测试,因为这样我就必须重新创建所有表。我还将旧样式的联接修改为当前样式,并使用了有意义的表别名。我用新联接格式编辑了原始查询。当我运行查询Sander时,它会给我一个错误。透视分组列必须是可比较的。“说明”列的类型为“文本”,这不是可比较的数据类型
text
似乎是。在最后的
select
group by
中,尝试将
ph.Description
替换为
convert(nvarchar(100),ph.Description)
。喜欢
with cte as
(
    SELECT TOP 1000
        --Start original selection field list
        ewo.EquipWorkOrderID,
        ewo.DateTm,
        equ.Equip,
        equ.AccountCode,
        equ.Descr,
        ewo.Description,
        ewo.Resolution,
        sta.Status,
        au.UserNm,
        ewoh.Hrs,
        cat.Category,
        ml.MaintLoc,
        equt.EquipType,
        cre.Crew,
        ewo.MeterReading,
        typ.Type,
        --Added two new fields
        'Usr' + convert(nvarchar(10),row_number() over(partition by Equip order by UserNm)) as 'UsrNum',
        'Hrs' + convert(nvarchar(10),row_number() over(partition by Equip order by UserNm)) as 'HrsNum'
    FROM EquipWorkOrder ewo
    JOIN EquipWorkOrderHrs ewoh
        ON ewo.EquipWorkOrderID = ewoh.EquipWorkOrderID
    JOIN AppUser au
        ON au.UserID = ewoh.UserID
    JOIN Category cat
        ON cat.CategoryID = ewo.CategoryID
    JOIN Crew cre
        ON cre.CrewID = ewo.CrewID
    JOIN Equipment equ
        ON equ.EquipmentID = ewo.EquipmentID
    JOIN Status sta
        ON sta.StatusID = ewo.StatusID
    JOIN PlantLoc pll
        ON pll.PlantLocID = ewo.PlantLocID
    JOIN MaintLocation ml
        ON ml.MaintLocationID = ewo.MaintLocationID
    JOIN EquipType equt
        ON equt.EquipTypeID = ewo.EquipTypeID
    JOIN Type typ
        ON typ.TypeID = equ.TypeID
    ORDER BY ewo.DateTm DESC
)
select ph.EquipWorkOrderId, ph.Equip, ph.Description, ph.Resolution,
       max(ph.Usr1) as 'UserNm1',
       max(ph.Hrs1) as 'Hrs1',
       max(ph.Usr2) as 'UserNm2',
       max(ph.Hrs2) as 'Hrs2'
from cte c
pivot (max(c.UserNm) for c.UsrNum in ([Usr1], [Usr2])) pu
pivot (max(pu.Hrs) for pu.HrsNum in ([Hrs1], [Hrs2])) ph
group by ph.EquipWorkOrderId, ph.Equip, ph.Description, ph.Resolution;
Select pivot_table.*
From
(
    Select  a.EquipWorkOrderID,
            b.Hrs,
            c.UserNm,
            'Tech' + convert(nvarchar(10), row_number() over(order by c.UserNm)) -- construct _generic_ names
    From EquipWorkOrder a
    Left Join EquipWorkOrderHrs b
        On a.EquipWorkOrderID = b.EquipWorkOrderID
    Left Join AppUser c
        On c.UserID = b.UserID
) t
/*
Pivot (Count(Hrs) For UserNm     IN ([Tech1], [Tech2], [Tech3], [Tech4], [Tech5])) AS pivot_table -- UserNm does not contain values like "Tech1" or "Tech2"
*/
Pivot (Count(Hrs) For GenUserNm  IN ([Tech1], [Tech2], [Tech3], [Tech4], [Tech5])) AS pivot_table -- pivot over the _generic_ names