Как включить пустые значения, используя динамически сводную в запросе, чтобы создать связь между столбцом и строкой - PullRequest
0 голосов
/ 14 января 2020

У меня есть запрос, который возвращает следующие результаты

+-----------+--------+-------+
| idPeriodo | codigo | valor |
+-----------+--------+-------+
|     1     |   7    |  1000 |
|     1     |   8    |  1000 | 
|     1     |   9    |  1000 | 
|     2     |   7    |  1000 | 
|     2     |   8    |  1000 | 
|     3     |   7    |  1000 | 
|     3     |   9    |  1000 |  
+-----------+--------+-------+

Мне нужно организовать запрос, потому что я создаю простой текстовый файл с результатами, поэтому в первую строку мне нужно поместить каждый "codi go" разбит на табуляцию, что-то вроде этого.

--This is the first row, is like a head
    7   8   9

После этого мне нужно поставить столбец "доблесть", связанный с его соответствующими codi go и idPeriodo. Окончательный результат должен быть примерно таким:

    7       8       9
1   1000    1000    1000
2   1000    1000    
3   1000            1000

Теперь у меня есть два запроса, первый - получить первую строку (голова со значениями codi go), а второй я делаю запрос для получения всех значений из столбца "valor", сгруппированных по idPeriodo. Эти мои запросы выглядят так.

-------Query to return head(codigo values)---------------
SELECT DISTINCT CONCAT(conjunto.codigo, central.confterm_id) as codigo_central 
FROM   mantenimiento_central_termica mantenimiento 
JOIN   configuracion_central_termica central 
ON     central.confterm_id = mantenimiento.confterm_id 
JOIN   conjunto_centrales conjunto
ON     central.id_conjuntocentral = conjunto.id

-------Query to return valor grouped by idPeriodo---------------
SELECT id_periodo , 
       valor_mantenimiento = string_agg(valor_mantenimiento, CHAR(9))
       WITHIN GROUP (ORDER BY codigo_central)
FROM(
SELECT CONCAT(conjunto.codigo, central.confterm_id) as codigo_central, 
       per_id                          AS id_periodo , 
       mantenimcentraltermica_potencia AS valor_mantenimiento 
FROM   mantenimiento_central_termica mantenimiento 
JOIN   configuracion_central_termica central 
ON     central.confterm_id = mantenimiento.confterm_id 
JOIN   conjunto_centrales conjunto
ON     central.id_conjuntocentral = conjunto.id
WHERE  cas_id = 2) main_thermal
GROUP BY id_periodo

Проблема, с которой я столкнулся, заключается в том, что второй запрос возвращает только значения из столбца valor, который не равен NULL, и когда я собираюсь разделить первый запрос на второй Я получаю что-то вроде этого:

    7       8       9
1   1000    1000    1000
2   1000    1000    
3   1000    2000    --The error is here, because the 2000 value must be in the third column, with the 9(codigo) value.

Мне нужно, чтобы запрос поставил пробел, когда нашел нулевое значение в отношении между codi go и idPeriodo.

Как я могу это сделать

Ответы [ 2 ]

1 голос
/ 14 января 2020

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

SELECT idPeriodo,
       MAX(CASE codigo WHEN 7 THEN valor END) AS [7],
       MAX(CASE codigo WHEN 8 THEN valor END) AS [8],
       MAX(CASE codigo WHEN 9 THEN valor END) AS [9]
FROM dbo.YourTable
GROUP BY idPeriodo;

Кажется, вам нужен динамический c пивот, который будет выглядеть следующим образом:

DECLARE @SQL nvarchar(MAX),
        @CRLF nchar(2) = NCHAR(13) + NCHAR(10);

SET @SQL = N'SELECT idPeriodo,' + @CRLF +
           STUFF((SELECT N',' + @CRLF +
                         N'       MAX(CASE codigo WHEN ' + QUOTENAME(codigo,'''') + N' THEN valor END) AS ' + QUOTENAME(codigo)
                  FROM dbo.YourTable
                  GROUP BY codigo
                  ORDER BY codigo
                  FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,3,N'') + @CRLF +
          N'FROM dbo.YourTable' + @CRLF +
          N'GROUP BY idPeriodo;';
--PRINT @SQL; --Your debugging friend.
EXEC sp_executesql @SQL;
0 голосов
/ 14 января 2020

Один вариант будет использовать pivot:

select idPeriodo, [7],[8],[9] 
  from tab
 pivot
 (
  max(valor) for codigo in ([7],[8],[9])
 ) t;

Демо

...