Отображать все заданные идентификаторы при использовании В операторе

#sql #sql-server #tsql #common-table-expression

#sql #sql-сервер #tsql #common-table-expression

Вопрос:

У меня есть CTE, который отображает каждую запись для каждого идентификатора пользователя по горизонтали (вместо обычного способа «перечисления») на основе заданного идентификатора пользователя и определенного диапазона дат. Я изо всех сил пытаюсь найти способ отобразить каждую предоставленную запись, потому что иногда в этот период этот пользователь не зарегистрирован, но мне все равно нужно знать, зарегистрировался он или нет. Я мог бы проверить вручную, но иногда я получаю более 200 идентификаторов.

Это то, что я получаю с моим текущим кодом

 id reg1 reg2 reg3
-----------------
x  a    b    c
  

Это это то, чего я ожидаю

 id reg1 reg2 reg3
-----------------
x  a    b    c
y  NULL NULL NULL -- 'y' doesn't exists, ergo, it should display the id and nulls on the rest of columns.
  

Мой код

 ;WITH CTE AS(
   SELECT PER_PRO, ID_HR, NOM_INC, rut_dv, dias_durAC, INI, FIN,
       ROW_NUMBER()OVER(PARTITION BY ID_HR ORDER BY ULT_ACT) AS RN
   FROM dbo.inf_lic WHERE PER_PRO = --GIVEN DATE PERIOD
)
SELECT ID_HR,rut_dv,NOM_INC,
       max(case when rn = 1 then DIAS_DURAC end) as DIAS_DUR1,
       max(case when rn = 1 then INI end) as INI1,
       max(case when rn = 1 then FIN end) as FIN1,

       max(case when rn = 2 then DIAS_DURAC end) as DIAS_DUR2,
       max(case when rn = 2 then INI end) as INI2,
       max(case when rn = 2 then FIN end) as FIN2,

       max(case when rn = 3 then DIAS_DURAC end) as DIAS_DUR3,
       max(case when rn = 3 then INI end) as INI3,
       max(case when rn = 3 then FIN end) as FIN3,

       max(case when rn = 4 then DIAS_DURAC end) as DIAS_DUR4,
       max(case when rn = 4 then INI end) as INI4,
       max(case when rn = 4 then FIN end) as FIN4
FROM CTE
WHERE RUT_DV in (/*GIVEN VALUES*/) 
GROUP BY ID_HR,RUT_DV, NOM_INC;
  

Комментарии:

1. Зачем вам вообще нужно использовать предложение IN? Ваш вопрос неясен, потому что ваши примеры данных и результаты не соответствуют именам столбцов в вашем коде.

2. Да, мне нужны данные из этих идентификаторов, независимо от того, существуют они или нет @TabAlleman

3. поместите весь список возможных идентификаторов, которые у вас есть, в представление (это должно быть что-то вроде select distinct (id) from table), затем выполните внешнее объединение слева вашего текущего запроса с этим представлением

Ответ №1:

Я бы предложил флаг «в период», который можно комбинировать с RN :

 WITH CTE AS(
      SELECT l.*,
             (CASE WHEN PER_PRO = ?
                   THEN ROW_NUMBER() OVER (PARTITION BY ID_HR ORDER BY ULT_ACT)
              END) as rn
      FROM dbo.inf_lic l
     )
SELECT ID_HR,rut_dv,NOM_INC,
       max(case when rn = 1 then DIAS_DURAC end) as DIAS_DUR1,
       max(case when rn = 1 then INI end) as INI1,
       max(case when rn = 1 then FIN end) as FIN1,

       max(case when rn = 2 then DIAS_DURAC end) as DIAS_DUR2,
       max(case when rn = 2 then INI end) as INI2,
       max(case when rn = 2 then FIN end) as FIN2,

       max(case when rn = 3 then DIAS_DURAC end) as DIAS_DUR3,
       max(case when rn = 3 then INI end) as INI3,
       max(case when rn = 3 then FIN end) as FIN3,

       max(case when rn = 4 then DIAS_DURAC end) as DIAS_DUR4,
       max(case when rn = 4 then INI end) as INI4,
       max(case when rn = 4 then FIN end) as FIN4
FROM CTE
WHERE RUT_DV in (/* GIVEN VALUES */) 
GROUP BY ID_HR, RUT_DV, NOM_INC;