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

时间:2019-10-20 19:34:45

标签: sql sql-server pivot

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

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

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

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

我怀疑它是数据透视表,但它们略高于我的水平。

(公司表)

Company_ID  Company_Name
-------------------------
1       Home Office
2       Stanton Office
3       NYC Office

(部门表)

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

2           OtherDept
2           ThatDept
2           BobsDept

(部门状态表)

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

注意:即使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

结果:

Company_ID      SalesStatus     InvStatus   RetailStatus    MaintStatus
--------------- --------------- ----------  -------------   ------------
1               InReview        InReview    Ready           Done

或者,对于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

结果:

Company_ID  OtherDeptStatus     ThatDeptStatus      BobsDeptStatus
----------  ----------------    --------------      --------------
2           InReview            Research            InReview

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

我认为描述我要执行的步骤是:

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

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

还有其他一些S.O.答案已经很接近我的要求,建议使用JOIN来完成此任务,但是,它们都假定您在编写join语句时就已经知道要查询的值。

我正在寻找解决此问题的方法,而不仅仅是对当前尝试的更正。如果您对如何完成此操作完全有更好的想法,我很乐意看到它。

2 个答案:

答案 0 :(得分:1)

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

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 

答案 1 :(得分:0)

这是我(未尝尝)穴居人解决问题的方法。 您唯一需要事先了解的是公司中拥有最多部门的几个不同部门。

DROP TABLE IF EXISTS Iddepartmentstatus;

DECLARE @Result TABLE(
                      Companyid   INT, 
                      Department1 NVARCHAR(MAX), 
                      Department2 NVARCHAR(MAX), 
                      Department3 NVARCHAR(MAX), 
                      Department4 NVARCHAR(MAX), 
                      Department5 NVARCHAR(MAX));

CREATE TABLE Iddepartmentstatus(
             Num        INT IDENTITY(1, 1), 
             Department NVARCHAR(MAX), 
             Statuscode NVARCHAR(MAX));

DECLARE @IDCompany TABLE(
                         Num         INT IDENTITY(1, 1), 
                         Companyid   INT, 
                         Companyname NVARCHAR(MAX));

INSERT INTO            @IDCompany (Companyid, 
                                   Companyname) 
       SELECT Company_Id, 
              Company_Name
       FROM   Company;

DECLARE @Departmentcount       INT = 0, 
        @Departmentstatuscount INT = 0, 
        @Companycount          INT = 0;

WHILE @Companycount <=
(
    SELECT MAX(Num)
    FROM   @IDCompany)
    BEGIN
        INSERT INTO                    Iddepartmentstatus (Department, 
                                                           Statuscode) 
               SELECT Department, 
                      Statuscode
               FROM   Departmentstatus
               WHERE  Company_Id = @Companycount;

        INSERT INTO         @Result (Companyid) 
               SELECT @Companycount AS T;

        INSERT INTO         @Result (Department1) 
               SELECT   IIF(1 <=
               (
                   SELECT MAX(Num)
                   FROM   @IDCompany), Department + ': ' + Departmentstatus, NULL)
               FROM Iddepartmentstatus
               WHERE    Num = 1;

        INSERT INTO         @Result (Department2) 
               SELECT   IIF(2 <=
               (
                   SELECT MAX(Num)
                   FROM   @IDCompany), Department + ': ' + Departmentstatus, NULL)
               FROM Iddepartmentstatus
               WHERE    Num = 2;

        INSERT INTO         @Result (Department3) 
               SELECT   IIF(3 <=
               (
                   SELECT MAX(Num)
                   FROM   @IDCompany), Department + ': ' + Departmentstatus, NULL)
               FROM Iddepartmentstatus
               WHERE    Num = 3;

        INSERT INTO         @Result (Department4) 
               SELECT   IIF(4 <=
               (
                   SELECT MAX(Num)
                   FROM   @IDCompany), Department + ': ' + Departmentstatus, NULL)
               FROM Iddepartmentstatus
               WHERE    Num = 4;

        INSERT INTO         @Result (Department5) 
               SELECT   IIF(5 <=
               (
                   SELECT MAX(Num)
                   FROM   @IDCompany), Department + ': ' + Departmentstatus, NULL)
               FROM Iddepartmentstatus
               WHERE    Num = 5;

        TRUNCATE TABLE Iddepartmentstatus;
        SET @Companycount = @Companycount + 1;
    END;
DROP TABLE IF EXISTS Iddepartmentstatus;