radhasapna Ответов: 1

Sqlpivot получает часть данных и выбирает в качестве строк столбец


Year	Q	Q2	Q3	Q4	
2000	200	456	45	35	
2000	200	435	435	545	
2000	200	454	43	45	
2000	200	45	435	4	
2001	300	4	43	545	
2001	300	43	4	56	
2001	300	4	4	4	
2001	300	43	43	6	
2001	300	4	56	34	
2002	400	4	34	43	
2002	400	43	45	6	
2002	400	4	45	4	
2002	400	43	34	54	
2002	400	45	45	6

у меня есть вышеуказанные данные, но я хочу, чтобы они были в другом формате
Year1	Q1	Q2	Q3	Q4	year	Q1	Q2	Q3	Q4	Year	Q	Q2	Q3	Q4
2000	200	456	45	35	2001	300	4	43	545	2002	400	4	34	43
2000	200	435	435	545	2001	300	43	4	56	2002	400	43	45	6
2000	200	454	43	45	2001	300	4	4	4	2002	400	4	45	4
2000	200	45	435	4	2001	300	43	43	6	2002	400	43	34	54


Что я уже пробовал:

я не получаю ни малейшего представления.

SELECT * FROM EDELGIVE_BUDGETSUMARY A 

left join EDELGIVE_BUDGETSUMARY B on a.BUDGET_YEAR = b.BUDGET_YEAR WHERE ( a.BUDGET_YEAR = b.BUDGET_YEAR )

1 Ответов

Рейтинг:
7

CHill60

Для этого вам не нужен PIVOT, но вы можете сделать это с помощью обычного табличного выражения.

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

2000	200	456	45	35
должен отображаться в той же строке, что и
2001	300	4	43	545
Это выглядит так, как будто вы используете "строка 1 из 2000 года идет со строкой 1 из 2001 года и строкой 1 из 2002 года" и т. д., Но у вас нет ничего, чтобы определить, что такое "строка 1", "строка 2" каждой группы - вам действительно нужен какой-то столбец идентификатора в вашей базовой таблице.

Я создал ваш образец данных с помощью этого:
create table #radhasapna ([Year] int, Q int, Q2 int, Q3 int, Q4 int)
insert into #radhasapna ([Year] , Q , Q2 , Q3 , Q4 ) values
(2000,	200,	456,	45,	35	),
(2000,	200,	435,	435,	545	),
(2000,	200,	454,	43,	45	),
(2000,	200,	45,	435,	4	),
(2001,	300,	4,	43,	545	),
(2001,	300,	43,	4,	56	),
(2001,	300,	4,	4,	4	),
(2001,	300,	43,	43,	6	),
(2001,	300,	4,	56,	34	),
(2002,	400,	4,	34,	43	),
(2002,	400,	43,	45,	6	),
(2002,	400,	4,	45,	4	),
(2002,	400,	43,	34,	54	),
(2002,	400,	45,	45,	6)
Оттуда я смог получить желаемые результаты, дав каждой строке в каждом году ROW_NUMBER (), а затем просто выполнив несколько соединений с результатами.
;with cte as
(
	SELECT ROW_NUMBER() OVER (PARTITION BY [Year] ORDER BY [Year]) as r, 
		[Year], Q, Q2, Q3, Q4
	FROM #radhasapna
)
select a.*, b.*, c.*
from cte a 
left outer join cte b on a.[Year] = b.[Year] and a.r = b.r
left outer join cte c on a.[Year] = c.[Year] and a.r = c.r
Мне пришлось поместить ORDER BY в оконную функцию, но константа не разрешена, поэтому я снова использовал [Year]... а это значит, что тот факт, что я получил правильные результаты, - чистая удача!

Но если я (вы!) определяю базовую таблицу следующим образом
create table #radhasapna (id int identity(1,1), [Year] int, Q int, Q2 int, Q3 int, Q4 int)
и использовать
;with cte as
(
	SELECT ROW_NUMBER() OVER (PARTITION BY [Year] ORDER BY id) as r,
		 [Year], Q, Q2, Q3, Q4
	FROM #radhasapna
)
select a.*, b.*, c.*
from cte a 
left outer join cte b on a.[Year] = b.[Year] and a.r = b.r
left outer join cte c on a.[Year] = c.[Year] and a.r = c.r
тогда ваши результаты гарантированы

-----------------------------------------------------------------------------
[EDIT] - OP указал, что количество лет может варьироваться.
-----------------------------------------------------------------------------

Вам нужно будет использовать динамический SQL, если количество лет может варьироваться, что-то вроде этого:
1. Установите некоторые начальные значения, "наименьший" год (@minY) и количество лет (@years) и основа для нашего динамического sql (@sql)
declare @years integer = (SELECT COUNT(DISTINCT [Year]) FROM #radhasapna)
declare @minY nvarchar(10) = (SELECT CAST(MIN([Year]) as nvarchar) FROM #radhasapna)

declare @sql nvarchar(max)
set @sql = ';with cte as (
	SELECT ROW_NUMBER() OVER (PARTITION BY [Year] ORDER BY id) as r,
		 [Year], Q, Q2, Q3, Q4
	FROM #radhasapna )
SELECT '
2. Замените то, что у меня было раньше, как
select a.*, b.*, c.*
с
select a1.*, a2.*, a3.*, etc
Обратите внимание, что теперь я использую a1, a2, a3 и т. д. В качестве псевдонимов таблиц...
declare @i int = 1
WHILE @i <= @years
begin
	set @sql = @sql + stuff('aXX', 2,2, @i) + '.*'
	if @i < @years
	begin
		set @sql = @sql + ','
	end 
	set @i = @i + 1
end
Если я PRINT @sql на данном этапе я получаю это
;with cte as (
	SELECT ROW_NUMBER() OVER (PARTITION BY [Year] ORDER BY id) as r,
		 [Year], Q, Q2, Q3, Q4
	FROM #radhasapna )
SELECT a1.*,a2.*,a3.*,a4.*,a5.*

3. Выясните, как выполнять соединения...
set @sql = @sql + ' from cte a1 '

set @i = 2
WHILE @i <= @years
begin
	declare @s nvarchar(10) = stuff('aXX', 2,2, @i)
	declare @prevS nvarchar(10) = stuff('aXX',2,2,@i-1)
	set @sql = @sql + 'left outer join cte ' + @s + ' on ' + @s + '.[Year] = ' + @prevS + '.[Year] + 1 and a1.r = ' + @s + '.r '
	set @i = @i + 1
end
Опять же, если я PRINT @sql теперь это было добавлено к концу
from cte a1 
left outer join cte a2 on a2.[Year] = a1.[Year] + 1 and a1.r = a2.r 
left outer join cte a3 on a3.[Year] = a2.[Year] + 1 and a1.r = a3.r 
left outer join cte a4 on a4.[Year] = a3.[Year] + 1 and a1.r = a4.r 
left outer join cte a5 on a5.[Year] = a4.[Year] + 1 and a1.r = a5.r 
4. Все, что осталось сделать, это поставить WHERE предложения и ORDER BY предложение в конце sql и запустите его
set @sql = @sql + 'where a1.[Year] = ' + @minY + ' order by a1.r'

EXEC sp_executesql @sql


radhasapna

Привет,
здесь distinct count of year равен 3, поэтому вы используете join 3 раза, но distinct count of year может быть any.so не определено, сколько раз мы должны использовать левое соединение. пожалуйста помочь

CHill60

Нам придется использовать динамический sql, чтобы обслуживать переменное количество лет. Посмотрим, что я смогу сделать сегодня. Я посмотрел на свое оригинальное решение и понял, что оно на самом деле не работает, поэтому я исправлю и это, когда у меня будет шанс

CHill60

Я обновил свое решение

radhasapna

невероятно....
да, он совершенен и точен.
буквально такой умный...
Еще раз большое вам спасибо

CHill60

С удовольствием