Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Unpivoting table
|
|||
|---|---|---|---|
|
#18+
Здравствуйте, все. Я тут зациклился с решением одной проблемы, возможно, кто-нибудь со свежим взглядом поможет решить ее более изящно. Проблема в следующем. Необходимо построить 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 раз. В случае курсора сканируем по прежнему однократно, но курсор на таких объемах уже заметно проигрывает в скорости и жрет много памяти. Конечно, в конце концов я протестирую оба варианта и выберу из двух зол меньшее, но м.б. кто-нибудь предложит менее тривиальное решение? Я намеренно описал всю задачу целиком, п.ч. м.б. сущ-т вообще другой путь и я напрасно уперся в это преобразование? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.05.2001, 09:50 |
|
||
|
Unpivoting table
|
|||
|---|---|---|---|
|
#18+
Существует еще и третий вариант: допустим еще есть некая таблица 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 раз, но если учесть что там есть всякая оптимизация и кеширование, может получиться быстрее, хотя и не факт. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.05.2001, 10:39 |
|
||
|
Unpivoting table
|
|||
|---|---|---|---|
|
#18+
Может быть имеет смысл перестроить базу и в качестве первичной таблицы взять Table1,а не Table0. Тогда с задачей транспонирования Вы столкнетесь, может быть, лишь в некоторых отчетах, где нужно всего лишь некоторое подмножество Table1. А вообще, для транспонирования таблицы(я имею ввиду перестановку столбец<->строка), предется явно или неявно перебрать каждый элемент, нуждающийся в перестановке. А Union, мне кажется наиболее изящное решение Вашей проблемы. С уважением, Попов АВ(Цунцуяби) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.05.2001, 15:43 |
|
||
|
Unpivoting table
|
|||
|---|---|---|---|
|
#18+
Перестроить базу не представляется возможным, поск. это эксплуатационная система и менять ее заказчик, ест-но, не даст. В итоге я остановился на след.варианте. В дополнении к существующей таблице (кол-во продуктов ограничено 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'ов, этот запрос работает не в пример быстрее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2001, 14:59 |
|
||
|
Unpivoting table
|
|||
|---|---|---|---|
|
#18+
У меня обратная задача как из table1 сделать table 0, может с помощью сохраненных процедур? Помогите очень надо для диплома. твой тезка dedmustdie@mail.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2001, 18:36 |
|
||
|
Unpivoting table
|
|||
|---|---|---|---|
|
#18+
Я в подобных случаях заводжу три таблицы, а не две. В одной продукты (таблица1), в другой даты (таблица2). Между ними отношение многие-ко-многим реализуется через третью таблицу (таблица3), в которой располагаю объем продаж, которая завязана с двумя другими отношениями один-ко-многим. Если нужно зайти на структуру в плане продуктов, строится запрос по таблице1 и таблице3. Если со стороны дат, то таблица2+таблица3. На всех трех можно получить любую другую информацию. Но ежели структура таблиц уже завязла в эпоксидке, то остается только развести руками... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2001, 21:25 |
|
||
|
Unpivoting table
|
|||
|---|---|---|---|
|
#18+
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" ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.05.2001, 09:51 |
|
||
|
Unpivoting table
|
|||
|---|---|---|---|
|
#18+
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 -- Те же ****, только с боку. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.05.2001, 09:17 |
|
||
|
Unpivoting table
|
|||
|---|---|---|---|
|
#18+
Доброе время суток! Вопрос к деду Маздаю. Извините за люботпытство, построение таблицы фактов (table1) проводиться над OLTP системой обработки заказов? Судя по table0 - нет. Если же это все-таки система обработки заказов, то структура table0 меня удивляет. Или должна быть другая (другие) таблица/ы со структурой близкой к table1. Заранее спасибо за ответ. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.10.2001, 18:11 |
|
||
|
Unpivoting table
|
|||
|---|---|---|---|
|
#18+
А я что? Я сам офигел. Но моя сфера влияния - это конкретный проект. В нем не указывается задача до основания разрушить весь мир насилья и на его обломках построить новый (мир насилья). Такова спортивная жизнь. В особо клинических случаях, когда видно, что здесь всю систему менять надо, мы предлагаем такие услуги клиенту. Вплоть до реинжиниринга бизнес-процессов. Но это стоит отдельных денег, на которые он не всегда идет, а иногда просто невозможно. Так что чаще всего приходится играть теми картами, что сданы. Я ответил на Ваш вопрос? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.10.2001, 06:04 |
|
||
|
Unpivoting table
|
|||
|---|---|---|---|
|
#18+
Что-то с памятью моей стало - дежа вю наверно, только тема эта полгодика назад уже подымалась - и тем же фигурантом... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.10.2001, 13:00 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=32005850&tid=1825298]: |
0ms |
get settings: |
8ms |
get forum list: |
19ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
32ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
60ms |
get tp. blocked users: |
1ms |
| others: | 249ms |
| total: | 388ms |

| 0 / 0 |
