powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Unpivoting table
12 сообщений из 12, страница 1 из 1
Unpivoting table
    #32005850
Фотография Дед Маздай
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте, все. Я тут зациклился с решением одной проблемы, возможно, кто-нибудь со свежим взглядом поможет решить ее более изящно. Проблема в следующем. Необходимо построить OLAP-куб из 2-х измерений - Время и Продукты - и одной меры, скажем, Продажи. Все они лежат в одной таблице фактов. Первая колонка у нее - это самое Время, а все остальные суть члены измерения Продукты (их порядка 20), которое, как вы видите, является абсолютно плоским одноуровневым измерением. Пересечение колонки Продукт_i со строкой с определенной датой, дает цифру продаж продукта за этот день, которая и есть мера. Все просто, за исключением того, что теория требует превратить эту перекрестную таблицу в звездочку, иными словами из Table0:
Время Продукт1 Продукт2 ... Продукт20
1997-01-01 100 200 ... 300
1997-01-02 400 500 ... 600
...
требуется сделать Table1:
Время Продукт Продажи
1997-01-01 Продукт1 100
1997-01-01 Продукт2 200
... ... ...
1997-01-01 Продукт20 300
1997-01-02 Продукт1 400
1997-01-02 Продукт2 500
... ... ...
1997-01-02 Продукт20 600
... ... ...

Так что задача сводится к чисто SQLной - как лучше преобразовать Table0 -> Table1. Я всегда решал такие вещи либо через union по числу полей, либо через курсор. На сей раз проблема, однако, состоит в том, что Table0 очень длинная - около 80Гб (на с.д. учет продаж ведется с точностью до минут, которые для ясности не показаны). Использование union означает увеличение времени сканирования в 20 раз. В случае курсора сканируем по прежнему однократно, но курсор на таких объемах уже заметно проигрывает в скорости и жрет много памяти.
Конечно, в конце концов я протестирую оба варианта и выберу из двух зол меньшее, но м.б. кто-нибудь предложит менее тривиальное решение? Я намеренно описал всю задачу целиком, п.ч. м.б. сущ-т вообще другой путь и я напрасно уперся в это преобразование?
...
Рейтинг: 0 / 0
Unpivoting table
    #32005856
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Существует еще и третий вариант:
допустим еще есть некая таблица n20(i int) просто с числами от 1 до 20
select time,
case i
when 1 then Продукт1
when 2 then Продукт2
when 3 then Продукт2
...
when 20 then Продукт20 end ,

case i
when 1 then Продажи1
when 2 then Продажи2
when 3 then Продажи2
...
when 20 then Продажи20 end

from Table0, n20

С одной стороны тоже сканирование таблицы 20 раз, но если учесть что там есть всякая оптимизация и кеширование, может получиться быстрее, хотя и не факт.
...
Рейтинг: 0 / 0
Unpivoting table
    #32005879
Может быть имеет смысл перестроить базу и в качестве первичной таблицы взять Table1,а не Table0.
Тогда с задачей транспонирования Вы столкнетесь, может быть, лишь в некоторых отчетах, где нужно всего лишь некоторое подмножество Table1.

А вообще, для транспонирования таблицы(я имею ввиду перестановку столбец<->строка), предется явно или неявно перебрать каждый элемент, нуждающийся в перестановке.

А Union, мне кажется наиболее изящное решение Вашей проблемы.

С уважением, Попов АВ(Цунцуяби)
...
Рейтинг: 0 / 0
Unpivoting table
    #32005940
Фотография Дед Маздай
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Перестроить базу не представляется возможным, поск. это эксплуатационная система и менять ее заказчик, ест-но, не даст. В итоге я остановился на след.варианте. В дополнении к существующей таблице (кол-во продуктов ограничено 5-ю для ясности)
CREATE TABLE [dbo].[Table1] (
[Time] [datetime] NULL ,
[Prod1] [float] NULL ,
[Prod2] [float] NULL ,
[Prod3] [float] NULL ,
[Prod4] [float] NULL ,
[Prod5] [float] NULL )
была создана и наполнена таблица-справочник продуктов
create table Table2 (ProdNumber int, ProdName varchar(10))
go
insert into Table2 values (1, 'Prod1')
insert into Table2 values (2, 'Prod2')
insert into Table2 values (3, 'Prod3')
insert into Table2 values (4, 'Prod4')
insert into Table2 values (5, 'Prod5')
После чего в кач-ве табл.фактов был использован view на запрос
select t1.[time], t2.ProdName,
case t2.ProdNumber when 1 then t1.Prod1
when 2 then t1.Prod2
when 3 then t1.Prod3
when 4 then t1.Prod4
when 5 then t1.Prod5
end as Sales
from Table1 t1 cross join Table2 t2
Т.е. реализована слегка модифицированная идея SergSuper, за что ему отдельное большое спасибо. Несмотря на то, что декартово произведение дает то же число записей, что и сумма union'ов, этот запрос работает не в пример быстрее.
...
Рейтинг: 0 / 0
Unpivoting table
    #32005959
Фотография Алексей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня обратная задача как из table1 сделать table 0, может с помощью сохраненных процедур?

Помогите очень надо для диплома.

твой тезка dedmustdie@mail.ru
...
Рейтинг: 0 / 0
Unpivoting table
    #32005964
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я в подобных случаях заводжу три таблицы, а не две. В одной продукты (таблица1), в другой даты (таблица2). Между ними отношение многие-ко-многим реализуется через третью таблицу (таблица3), в которой располагаю объем продаж, которая завязана с двумя другими отношениями один-ко-многим. Если нужно зайти на структуру в плане продуктов, строится запрос по таблице1 и таблице3. Если со стороны дат, то таблица2+таблица3. На всех трех можно получить любую другую информацию. Но ежели структура таблиц уже завязла в эпоксидке, то остается только развести руками...
...
Рейтинг: 0 / 0
Unpivoting table
    #32005980
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Дед Маздай
отдельное большое пожалуйста
как говориться, друзья познаются в БД

2 Алексей

Вариант для диплома:

select t1.time, t1.Prod, t2.Prod, t3.Prod, t4.Prod, t5.Prod
from Table1 t1,Table1 t2,Table1 t3,Table1 t4,Table1 t5
where t1.time=t2.time and t1.time=t3.time and t1.time=t4.time and t1.time=t5.time
and t1.Sales='Prod1' and t2.Sales='Prod2' and t3.Sales='Prod3' and t4.Sales='Prod4' and t5.Sales='Prod5'

Но так можно написать только для диплома, в "жизни" я бы так не делал: допустим если у нас нет за какое-то время продаж только по одному продукту, то не попадут и все остальные за это время. Надо использовать тогда outer joinы, но уж больно мне лениво этот запросище писать.


Я обычно делаю через временную таблицу:

create table #t(time datetime, Продажи1 money,Продажи2 money,Продажи3 money,Продажи4 money,Продажи5 money)

insert #t time, Prod,0,0,0,0 from Table1 where Sales='Prod1'
insert #t time, 0,Prod,0,0,0 from Table1 where Sales='Prod2'
insert #t time, 0,0,Prod,0,0 from Table1 where Sales='Prod3'
insert #t time, 0,0,0,Prod,0 from Table1 where Sales='Prod4'
insert #t time, 0,0,0,0,Prod from Table1 where Sales='Prod5'

select time, sum(Продажи1), sum(Продажи2), sum(Продажи3), sum(Продажи4), sum(Продажи5)
from #t
group by time

Я кажется с именами полей напутал, но думаю суть понятна. Причем здесь сохраненные процедуры и как они могут помочь я не понял.

С приветом Сергей
PS. Мне бы в свое время такую тему диплома. А то у меня была "Проэт АЭС с реактором РБМК-1500"
...
Рейтинг: 0 / 0
Unpivoting table
    #32006056
Fompro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Алексей
Для трансп. таблицы, где значения м.б. не только Numeric:
CREATE TABLE #Val (GrpId int, FldId char(1),CVal char(10 ))
CREATE TABLE #Fld (FldId char(1),RId int)
INSERT #Val VALUES(1, 'A', '41')
INSERT #Val VALUES(2, 'D', '609')
INSERT #Val VALUES(2, 'C', '888')
INSERT #Val VALUES(1, 'B', '20010521')
INSERT #Val VALUES(2, 'A', '44')
INSERT #Val VALUES(1, 'D', '67')
INSERT #Val VALUES(1, 'C', '89')
INSERT #Val VALUES(2, 'B', '20010523')
INSERT #Fld VALUES('A', 1)
INSERT #Fld VALUES('B', 2)
INSERT #Fld VALUES('C', 3)
INSERT #Fld VALUES('D', 4)
SELECT V.GrpId,Fld1=MAX(CASE WHEN F.RId=1 THEN V.CVal ELSE NULL END),
Fld2=MAX(CASE WHEN F.RId=2 THEN CAST(V.CVal AS datetime) ELSE NULL END),
Fld3=MAX(CASE WHEN F.RId=3 THEN CAST(V.CVal AS int) ELSE NULL END),
Fld4=MAX(CASE WHEN F.RId=4 THEN V.CVal ELSE NULL END) --
FROM #Val V JOIN #Fld F ON (V.FldId=F.FldId)
GROUP BY V.GrpId
DROP TABLE #Fld
DROP TABLE #Val --
Те же ****, только с боку.
...
Рейтинг: 0 / 0
Unpivoting table
    #32015295
Евгений К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброе время суток! Вопрос к деду Маздаю.
Извините за люботпытство, построение таблицы фактов (table1) проводиться над OLTP системой обработки заказов? Судя по table0 - нет. Если же это все-таки система обработки заказов, то структура table0 меня удивляет. Или должна быть другая (другие) таблица/ы со структурой близкой к table1.
Заранее спасибо за ответ.
...
Рейтинг: 0 / 0
Unpivoting table
    #32015383
Фотография Дед Маздай
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А я что? Я сам офигел. Но моя сфера влияния - это конкретный проект. В нем не указывается задача до основания разрушить весь мир насилья и на его обломках построить новый (мир насилья). Такова спортивная жизнь. В особо клинических случаях, когда видно, что здесь всю систему менять надо, мы предлагаем такие услуги клиенту. Вплоть до реинжиниринга бизнес-процессов. Но это стоит отдельных денег, на которые он не всегда идет, а иногда просто невозможно. Так что чаще всего приходится играть теми картами, что сданы. Я ответил на Ваш вопрос?
...
Рейтинг: 0 / 0
Unpivoting table
    #32015413
Фотография AnS1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то с памятью моей стало - дежа вю наверно,
только тема эта полгодика назад уже подымалась - и тем же
фигурантом...
...
Рейтинг: 0 / 0
Unpivoting table
    #32015414
Евгений К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, вполне.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Unpivoting table
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]