Как вращать / поворачивать несколько SQL таблиц с произвольным количеством столбцов? - PullRequest
1 голос
/ 26 марта 2020

У меня есть несколько (широких) таблиц:

  • большое количество столбцов
  • имена столбцов не совпадают между таблицами
  • идентификаторы перекрытие между таблицами

Пример:

wide_table1 :

| id | timestamp | col1     | col2    | ... | col200    |
|----|-----------|----------|---------|-----|-----------| 
|1   | 11        | 1.001    | 7.004   | ... | 1.240     |
|2   | 12        | 6.003    | NULL    | ... | 2.201     |
|... | ...       | ...      | ...     | ... |  ....     |
|5000| 5010      | 5020.009 | 5001.402| ... | 5085.210  |

wide_table2 :

| id | timestamp | col201   | col202  | ... | col706 |
|----|-----------|----------|---------|-----|--------| 
|1   | 104       | 7.051    | 1.004   | ... | 6.270  |
|... | ...       | ...      | ...     | ... |  ....  |
|9000| 8010      | NULL     | 301.002 | ... | 535.10 |

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

Как можно повернуть / повернуть эти 2 таблицы в одну, чтобы получить что-то вроде this:

long_table :

| id | timestamp | colum_name | value  |
|----|-----------|------------|--------|
|1   |11         |col1        |1.001   |
|1   |11         |col2        |7.004   |
|... |...        |...         |...     |
|1   |11         |col200      |1.240   |
|2   |12         |col1        |6.003   |
|2   |12         |col2        |NULL    |
|... |...        |...         |...     |
|2   |12         |col200      |2.201   |
|... |...        |...         |...     |
|5000|5010       |col1        |5020.009|
|5000|5010       |col2        |5001.402|
|... |...        |...         |...     |
|5000|5010       |col200      |5085.210|
|1   |104        |col201      |7.051   |
|1   |104        |col202      |1.004   |
|... |...        |...         |...     |
|1   |104        |col706      |6.270   |
|... |...        |...         |...     |
|9000|8010       |col201      |NULL    |
|9000|8010       |col202      |301.002 |
|... |...        |...         |...     |
|9000|8010       |col706      |535.10  |

Если возможно, я не хочу поддерживать все имена столбцов в операторе SQL, потому что схема изменится в будущем несколько раз.

Ответы [ 3 ]

2 голосов
/ 26 марта 2020

Я вижу большое количество столбцов. Если 2016+, вы можете использовать бит JSON для динамического удаления данных без фактического использования Dynami c SQL.

Я должен добавить NULL значения будут исключены.

Если <2016, существует аналогичный XML подход. </p>

Пример

Select A.ID
      ,A.TimeStamp
      ,B.* 
 from  YourTable A
 Cross Apply (
                Select colum_name = [Key]
                      ,[value]
                 From OpenJson((Select A.* For JSON Path,Without_Array_Wrapper ) ) 
                 Where [Key] not in ('ID','timestamp')
             ) B
2 голосов
/ 26 марта 2020

Используйте union all и apply:

select t1.id, t1.timestamp, v.*
from t1 cross apply
     (values ('col1', t1.col1),
             ('col2', t1.col2),
             . . .
     ) v(colname, value)
union all
select t2.id, t2.timestamp, v.*
from t2 cross apply
     (values ('col1', t1.col1),
             ('col2', t1.col2),
             . . .
     ) v(colname, value);
1 голос
/ 26 марта 2020

Вы вероятно хотите использовать для этого Dynami c SQL:

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

SET @SQL = N'SELECT YT.Id,' + @CRLF + 
           N'       YT.[timestamp],' + @CRLF +  
           N'       V.[ColumnName],' + @CRLF + 
           N'       V.ColumnValue' + @CRLF   +
           N'FROM dbo.YourTable YT' + 
           N'     CROSS APPLY (VALUES' +
           (SELECT STRING_AGG('(N' + QUOTENAME(c.[name],'''') + N',' + QUOTENAME(c.[name]) + N')',@Delimiter) WITHIN GROUP (ORDER BY C.column_id)
            FROM sys.schemas s
                 JOIN sys.tables t ON s.schema_id = t.schema_id
                 JOIN sys.columns c ON t.object_id = c.object_id
            WHERE s.[name] = N'dbo'
              AND t.[name] = N'YourTable') + N')V(ColumnName,ColumnValue);';

PRINT @SQL;-- Use SELECT for values over 4,000 characters

EXEC sp_executesql @SQL;

Очевидно, замените YourTable и dbo на правильные имена таблиц и схем .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...