Поля преобразования таблицы TSQL => Столбцы - PullRequest
1 голос
/ 27 августа 2010

У меня следующая таблица таблиц.Каждое значение строки всегда будет уникальным.Никогда не будет более одного экземпляра одного и того же Id, Name и Line.

Id Name Line
1  A    Z
2  B    Y
3  C    X
3  C    W
4  D    W

Я бы хотел запросить данные, чтобы поле Line стало столбцом.Если значение существует, в данных поля применяется 1, в противном случае - 0. Например,

Id Name Z Y X W
1  A    1 0 0 0
2  B    0 1 0 0
3  C    0 0 1 1
4  D    0 0 0 1

Имена полей W, X, Y, Z являются просто примерами значений полей, поэтому я не могуприменить оператор для явной проверки, например, «X», «Y» или «Z».Они могут измениться в любое время и не ограничены конечным набором значений.Имена столбцов в наборе результатов должны отражать уникальные значения полей в виде столбцов.

Есть идеи, как мне этого добиться?

Ответы [ 7 ]

6 голосов
/ 27 августа 2010

Это стандартный сводный запрос.

Если 1 представляет логический индикатор - используйте:

  SELECT t.id,
         t.name,
         MAX(CASE WHEN t.line = 'Z' THEN 1 ELSE 0 END) AS Z,
         MAX(CASE WHEN t.line = 'Y' THEN 1 ELSE 0 END) AS Y,
         MAX(CASE WHEN t.line = 'X' THEN 1 ELSE 0 END) AS X,
         MAX(CASE WHEN t.line = 'W' THEN 1 ELSE 0 END) AS W
    FROM TABLE t
GROUP BY t.id, t.name

Если 1 представляет количество записей с этим значением для группы, используйте:

  SELECT t.id,
         t.name,
         SUM(CASE WHEN t.line = 'Z' THEN 1 ELSE 0 END) AS Z,
         SUM(CASE WHEN t.line = 'Y' THEN 1 ELSE 0 END) AS Y,
         SUM(CASE WHEN t.line = 'X' THEN 1 ELSE 0 END) AS X,
         SUM(CASE WHEN t.line = 'W' THEN 1 ELSE 0 END) AS W
    FROM TABLE t
GROUP BY t.id, t.name
2 голосов
/ 27 августа 2010

Вот динамическая версия

Тестовый стол

create table #test(id int,name char(1),line char(1))

insert #test values(1 , 'A','Z')
insert #test values(2 , 'B','Y')
insert #test values(3 , 'C','X')
insert #test values(4 , 'C','W')
insert #test values(5 , 'D','W')
insert #test values(5 , 'D','W')
insert #test values(5 , 'D','P')

Теперь запустите это

declare @names nvarchar(4000)

SELECT @names =''
  SELECT  @names    = @names +   line +', '  
    FROM (SELECT distinct  line from #test) x

SELECT @names = LEFT(@names,(LEN(@names) -1))

exec('
SELECT *
 FROM(
SELECT DISTINCT Id, Name,Line
FROM #test
    ) AS pivTemp
PIVOT
(   COUNT(Line)
    FOR Line IN (' + @names +' )
) AS pivTable ')

Теперь добавьте одну строку в таблицу и снова выполните запрос выше, и вы увидите B

insert #test values(5 , 'D','B')

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

2 голосов
/ 27 августа 2010

Отредактировано после обновления в вопросе

SQL Server не поддерживает динамическое вращение.

Для этого вы можете использовать динамический SQL для генерации запроса по следующейlines.

SELECT 
       Id ,Name, 
       ISNULL(MAX(CASE WHEN Line='Z' THEN 1 END),0) AS Z,
       ISNULL(MAX(CASE WHEN Line='Y' THEN 1 END),0) AS Y,
       ISNULL(MAX(CASE WHEN Line='X' THEN 1 END),0) AS X,
       ISNULL(MAX(CASE WHEN Line='W' THEN 1 END),0) AS W
FROM T
 GROUP BY Id ,Name

Или альтернатива, о которой я читал, но на самом деле не пробовал, - это использовать функцию Access Transform, настроив базу данных Access со связанной таблицей, указывающей на таблицу SQL Server, а затем запроситеДоступ к базе данных с SQL Server!

1 голос
/ 27 августа 2010

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

declare @MyTable table (
    Id int,
    Name char(1),
    Line char(1)
)

insert into @MyTable
    (Id, Name, Line)
    select 1,'A','Z'
    union all
    select 2,'B','Y'
    union all
    select 3,'C','X'
    union all
    select 3,'C','W'
    union all
    select 4,'D','W'

SELECT Id, Name, Z, Y, X, W
    FROM (SELECT Id, Name, Line
            FROM @MyTable) up
    PIVOT (count(Line) FOR Line IN (Z, Y, X, W)) AS pvt
    ORDER BY Id
0 голосов
/ 28 августа 2010

Вот довольно экзотический подход (с использованием примеров данных из старой базы данных Northwind). Он адаптирован с версии здесь , которая больше не работает из-за устаревания DBCC RENAMECOLUMN и добавления PIVOT в качестве ключевого слова.

set nocount on 
create table Sales ( 
  AccountCode char(5), 
  Category varchar(10), 
  Amount decimal(8,2) 
) 
--Populate table with sample data 
insert into Sales 
select customerID, 'Emp'+CAST(EmployeeID as char), sum(Freight) 
from Northwind.dbo.orders 
group by customerID, EmployeeID 
create unique clustered index Sales_AC_C 
on Sales(AccountCode,Category) 
--Create table to hold data column names and positions 
select A.Category, 
       count(distinct B.Category) AS Position 
into #columns 
from Sales A join Sales B 
on A.Category >= B.Category 
group by A.Category 
create unique clustered index #columns_P on #columns(Position) 
create unique index #columns_C on #columns(Category) 
--Generate first column of Pivot table 
select distinct AccountCode into Pivoted from Sales 
--Find number of data columns to be added to Pivoted table 
declare @datacols int 
select @datacols = max(Position) from #columns 
--Add data columns one by one in the correct order 
declare @i int 
set @i = 0 
while @i < @datacols begin 
  set @i = @i + 1 
--Add next data column to Pivoted table 
  select P.*, isnull(( 
    select Amount 
    from Sales S join #columns C 
    on C.Position = @i 
    and C.Category = S.Category 
    where P.AccountCode = S.AccountCode),0) AS X 
  into PivotedAugmented 
  from Pivoted P 
--Name new data column correctly 
  declare @c sysname 
  select @c = Category 
  from #columns 
  where Position = @i 
  exec sp_rename '[dbo].[PivotedAugmented].[X]', @c, 'COLUMN'
--Replace Pivoted table with new table 
  drop table Pivoted 
  select * into Pivoted from PivotedAugmented 
  drop table PivotedAugmented 
end 
select * from Pivoted 
go 
drop table Pivoted 
drop table #columns 
drop table Sales 
0 голосов
/ 28 августа 2010

Если вы делаете это для отчета служб отчетов SQL Server (SSRS) или можете переключиться на его использование, остановитесь сейчас и добавьте элемент Matrix в свой отчет. Пуф! Вы сделали! Доволен, как моллюск, с вашими данными.

0 голосов
/ 27 августа 2010

Поскольку вы используете SQL Server, вы можете использовать оператор PIVOT , предназначенный для этой цели.

...