Выбрать строки в одной таблице на основе значений столбцов в другой таблице? - PullRequest
3 голосов
/ 20 октября 2019

Мне нужно выбрать один столбец для каждой подходящей строки в другой таблице. Звучит просто, но есть поворот.

  • У меня есть одна таблица с идентификаторами компаний и определения компаний.
  • У меня есть еще одна таблица, которая определяет отделы в этих компаниях.
  • У меня есть третья таблица, в которой содержатся различные коды состояния отдела.

Код, который у меня ниже, прекрасно работает, и это именно то, чего я хочу. Но я должен жестко указать в запросе, какие отделы искать. Я бы хотел, чтобы он выбирал на основе кодов отделов, которые он находит в таблице «Отделы», и не требовал, чтобы я жестко кодировал каждый возможный отдел, который может существовать в этой компании.

Мне нужно выбрать соответствующий отделстатус от DepartmentStatus, основанный на том, какие отделы существуют для компании, как определено в таблице DepartmentsStatus.

Я подозреваю, что это сводная таблица, но они немного выше моего уровня.

(Таблица компании)

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

(таблица DepartmentStatus)

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

Примечание: я использую «TOP 1», хотя естьуникальный индекс для Company_ID + Department, поэтому никогда не будет более одной подходящей строки.

Итак, для 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 мне нужно получить статус отдела продаж, инвентарь, Розничная торговля и Maint. Но для Компании 2 мне нужно получить статус для Отделов OtherDept, ThatDept и BobsDept.

Шаги, которые, я думаю, описывают то, что я пытаюсь сделать, это:

  1. Получитьсписок отделов для компании 1 из таблицы отделов.
  2. Для каждого из этих отделов на шаге 1 запрос таблицы DepartmentStatus для Department равен этому отделу. Для компании 1 запрос получить код состояния Status для отделов «Sales, Inventory, Retail и Maint». Для компании 2 запрос получить код состояния Status для отделов «OtherDept, thatDept и BobsDept». и т. д. и т. д.

Проблема в том, что я не знаю заранее (во время запроса), какие отделы существуют для каждой компании, поэтому мне нужно выбрать дополнительный, основываясь на том, какие отделы существуют для каждой компании. .

Уже есть несколько других ответов SO, которые близки к тому, что я прошу, предлагая использовать JOIN для достижения этой цели, однако все они предполагают, что вы знаете значения, которые хотите запросить заранее. времени при написании оператора соединения.

Я ищу решение этой проблемы, а не просто исправление моей текущей попытки. Если бы у вас была лучшая идея о том, как этого добиться, я бы хотел это увидеть.

Ответы [ 2 ]

1 голос
/ 20 октября 2019

Вы, похоже, ищете условную агрегацию. Используя эту технику, ваш запрос может быть упрощен следующим образом, чтобы избежать необходимости в нескольких встроенных подзапросах:

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 
0 голосов
/ 21 октября 2019

это был бы мой (непроверенный) способ пещерного человека решить вашу проблему. единственное, что вам нужно знать заранее, это количество различных отделов в вашей компании с наибольшим количеством отделов.

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...