SQL Server: динамически создавать столбцы из столбца идентификатора, связанного с другой таблицей - PullRequest
0 голосов
/ 06 декабря 2018

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

Посмотрите на приведенный ниже пример - «Текущая таблица» - это то, как она выглядит сейчас.У меня есть столбец для каждого имени.Я уже создал таблицу определений.Я хочу, чтобы текущая таблица выглядела как предлагаемая таблица и «СОЗДАВАЛА» столбцы в выборке или что-то в этом роде, используя таблицу определений для имен, которые выглядят так, как сейчас.

enter image description here

Ответы [ 3 ]

0 голосов
/ 06 декабря 2018

Вот один из подходов, который «динамически» разворачивает ваши данные без фактического использования динамического SQL.

Очевидно, что Гордона будет более производительным, но здесь вам не нужно объявлять столбцы.

Пример

Select  D.id
       ,[count] = C.Value
       ,A.ts
 From  CurrentTable A
 Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
 Cross Apply (
                Select Item = a.value('local-name(.)','varchar(100)')
                      ,Value = a.value('.','int')    -- Use appropriate type
                 From  B.XMLData.nodes('/row')  as C1(n)
                 Cross Apply C1.n.nodes('./@*') as C2(a)
                 Where a.value('local-name(.)','varchar(100)') not in ('ts','OtherColToExclude')
             ) C
 Join   definition D on C.item=D.Name

Возвращает

id  count   ts
1   5       2018-12-06
2   88      2018-11-01
2   18      2018-10-18
3   32      2018-10-27
4   6       2018-10-27
0 голосов
/ 02 января 2019

Также вы можете попробовать использовать unpivot для достижения ваших требований.Для более подробной информации, вы можете обратиться к этой статье: https://docs.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot?view=sql-server-2017

----drop table [current_table] 
----drop table [definition] 
create table [current_table] 
(p1 int,
p2 int,
p3 int,
p4 int,
ts date )
insert into [current_table] values
(5,null,null,null,'20181206'),
(null,88,null,null,'20181101'),
(null,18,null,null,'20181018'),
(null,null,32,null,'20181027'),
(null,null,null,6,'20181014')

create table [definition] 
(id int,
name varchar(5) )
insert into [definition] values 
(1,'p1'),(2,'p2'),
(3,'p3'),(4,'p4')

;with cte as (
SELECT [name] ,[count],ts 
FROM [current_table]  t
UNPIVOT ([count] FOR [name] IN ([p1],[p2],[p3],[p4])) u)
select b.id,a.count,a.ts from  cte a  join [definition] b on a.name=b.name
/*
id          count       ts
----------- ----------- ----------
1           5           2018-12-06
2           88          2018-11-01
2           18          2018-10-18
3           32          2018-10-27
4           6           2018-10-14
*/


------dynamic-------------
DECLARE @ColNames varchar(1000);
SET @ColNames = '';
SELECT @ColNames =stuff((
    SELECT DISTINCT ',' + QUOTENAME(COLUMN_NAME)
    FROM INFORMATION_SCHEMA.COLUMNS p2
    WHERE TABLE_NAME = 'current_table'
      AND COLUMN_NAME like 'p%'
    FOR XML PATH(''), TYPE).value('.', 'varchar(max)')
            ,1,1,'')
DECLARE @CMD nvarchar(2000);
SET @CMD = ';with cte as (
SELECT [name] ,[count],ts 
FROM [current_table]  t
UNPIVOT ([count] FOR [name] IN ('+@ColNames+')) u)
select b.id,a.count,a.ts from  cte a  join [definition] b on a.name=b.name'
PRINT @CMD
execute sp_executesql @CMD
/*
;with cte as (
SELECT [name] ,[count],ts 
FROM [current_table]  t
UNPIVOT ([count] FOR [name] IN ([p1],[p2],[p3],[p4])) u)
select b.id,a.count,a.ts from  cte a  join [definition] b on a.name=b.name
id          count       ts
----------- ----------- ----------
1           5           2018-12-06
2           88          2018-11-01
2           18          2018-10-18
3           32          2018-10-27
4           6           2018-10-14
*/

Надеюсь, что это может помочь вам.

С наилучшими пожеланиями,

Рейчел

0 голосов
/ 06 декабря 2018

Это очень странная структура данных.Вот один из методов:

select d.id as definition,
       coalesce(c.p1, c.p2, c.p3, c.p4) as "count",
       c.ts
from current_table c join
     definition d
     on (d.name = 'p1' and p1 is not null) or
        (d.name = 'p2' and p2 is not null) or
        (d.name = 'p3' and p3 is not null) or
        (d.name = 'p4' and p4 is not null) ;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...