根据另一个表中的列值选择一个表中的行?

Kir*_*ace 5 sql sql-server pivot inner-join aggregate-functions

我需要为另一个表中的每个匹配行选择一列。听起来很简单,但有一个转折。

  • 我有一张表,其中包含公司 ID,并定义了公司。
  • 我有另一个表定义了这些公司的部门。
  • 我有第三个表,其中包含各种部门状态代码。

我下面的代码工作得很好,并且正是我想要的。但我必须将要查找的部门硬编码到查询中。我希望它根据在“部门”表中找到的部门代码进行子选择,而不要求我对该公司可能存在的每个可能的部门进行硬编码。

我需要根据 DepartmentsStatus 表中定义的公司存在的部门,从 DepartmentStatus 选择匹配的部门状态。

我怀疑这是一个数据透视表,但它们比我的水平高一点。

(公司表)

Company_ID  Company_Name
-------------------------
1       Home Office
2       Stanton Office
3       NYC Office
Run Code Online (Sandbox Code Playgroud)

(部门表)

CompanyID   Department_Code
----------------------------
1           Sales
1           Inventory
1           Retail
1           Maint

2           OtherDept
2           ThatDept
2           BobsDept
Run Code Online (Sandbox Code Playgroud)

(部门状态表)

Company_ID  Department  StatusCode
-----------------------------------------
1           Sales       InReview
1           Inventory   InReview
1           Retail      Ready
1           Maint       Done
2           OtherDept   InReview
2           ThatDept    Research
2           BobsDept    InReview
Run Code Online (Sandbox Code Playgroud)

注意:即使 Company_ID+Department 上有唯一索引,我也使用“TOP 1”,因此永远不会有多个匹配行。

因此,对于 Company_ID=1:

select  Company_ID,  
        (select top 1 StatusCode from DepartmentStatus ds where ds.Company_ID = cm.Company_ID and ds.Department='Sales') as SalesStatus
        (select top 1 StatusCode from DepartmentStatus ds where ds.Company_ID = cm.Company_ID and ds.Department='Inventory') as InvStatus
        (select top 1 StatusCode from DepartmentStatus ds where ds.Company_ID = cm.Company_ID and ds.Department='Retail') as RetailStatus
        (select top 1 StatusCode from DepartmentStatus ds where ds.Company_ID = cm.Company_ID and ds.Department='Main') as MaintStatus
from    Company cm
Where   cm.CompanyID=1
Run Code Online (Sandbox Code Playgroud)

结果:

Company_ID      SalesStatus     InvStatus   RetailStatus    MaintStatus
--------------- --------------- ----------  -------------   ------------
1               InReview        InReview    Ready           Done
Run Code Online (Sandbox Code Playgroud)

或者,对于 CompanyID=2:

select  Company_ID,  
        (select top 1 StatusCode from DepartmentStatus ds where ds.CompanyID = cm.Company_ID and ds.Department='OtherDept') as OtherDeptStatus
        (select top 1 StatusCode from DepartmentStatus ds where ds.CompanyID = cm.Company_ID and ds.Department='ThatDept') as ThatDeptStatus
        (select top 1 StatusCode from DepartmentStatus ds where ds.CompanyID = cm.Company_ID and ds.Department='BobsDept') as BobsDeptStatus
from    Company cm
Where   cm.CompanyID=2
Run Code Online (Sandbox Code Playgroud)

结果:

Company_ID  OtherDeptStatus     ThatDeptStatus      BobsDeptStatus
----------  ----------------    --------------      --------------
2           InReview            Research            InReview
Run Code Online (Sandbox Code Playgroud)

因此,对于公司 1,我需要获取销售、库存、零售和维护部门的状态。但对于公司 2,我需要获取其他部门、ThatDept 和 BobsDept 部门的状态。

我认为描述我正在尝试做的步骤是:

  1. 从部门表中获取公司 1 的部门列表。
  2. 对于步骤 1 中的每个部门,查询 DepartmentStatus 表中是否有等于该部门的部门。对于公司 1,查询获取部门“销售、库存、零售和维护”的 StatusCode 对于公司 2,查询获取部门“OtherDept、thatDept 和 BobsDept”的 StatusCode。等等等等

问题是,我不提前(在查询时)知道每个公司存在哪些部门,因此我需要根据每个公司实际存在的部门进行子选择。

已经有一些其他答案接近我的要求,建议使用 JOIN 来完成此操作,但是,它们都假设您在编写 join 语句时提前知道要查询的值。

我正在寻找解决这个问题的方法,而不仅仅是纠正我当前的尝试。如果您对如何实现这一目标有更好的想法,我很乐意看到。

GMB*_*GMB 3

您似乎正在寻找条件聚合。使用此技术,您的查询可以简化如下,以避免需要多个内联子查询:

select  Company_ID,  
        max(case when ds.Department='Sales' then ds.StatusCode end) as SalesStatus,
        max(case when ds.Department='Inventory' then ds.StatusCode end) as InvStatus,
        max(case when ds.Department='Retail' then ds.StatusCode end) as RetailStatus,
        max(case when ds.Department='Main' then ds.StatusCode end) as MaintStatus
from    
    Company cm
    inner join DepartmentStatus ds on ds.Company_ID = cm.Company_ID 
Where   cm.CompanyID=1
group by cm.CompanyID 
Run Code Online (Sandbox Code Playgroud)