QlikView был и остается непревзойденным продуктом для визуальной аналитики и интерактивной навигации по бизнес-данным. На практике же, сценарии применения QlikView простираются шире, чем только лишь представление данных на экране в пользовательском интерфейсе. Так, в своем проектном опыте, я встречал много ситуаций, когда QlikView был инструментом подготовки данных в табличной структуре для их последующей передачи в другие приложения и системы.
В данной статье я расскажу о наиболее интересных реализациях таких задач в порядке «от простого к сложному». Сначала – несколько слов о ручном переносе данных из чартов QlikView в Excel, CSV и другие форматы; далее – способы автоматизированного переноса данных из ассоциативной модели QlikView в CSV/таблицу СУБД; ну и «на десерт» — задача автоматического переноса данных из Qlik-а с помощью NPrinting.
I. Ручной перенос данных из чартов QV в Excel/CSV/QVD
Самая часто встречающаяся задача: пользователь хочет перенести набор данных (значения показателей в разрезе выбранных элементов измерений) из чарта в интерфейсе приложения QV (плоской или сводной таблицы) к себе в настольное приложение MS Excel/Access/QV/Sense, чтобы самостоятельно проработать с ним — связать с другими данными, построить свои сводные таблицы и графики.
Давайте разберем несколько способов, с помощью которых это можно сделать.
Способ 1. Простейший способ — команда контекстного меню в интерфейсе: Send To Excel (Отправить в Excel).
Этот способ отлично работает, когда количество строк в чарте QlikView невелико — существенно меньше одного миллиона. Если до 65 тысяч — выгрузка будет выполнена в формате XLS, если больше — то в CSV. В обоих случаях будет запущен MS Excel, и QV некоторое время будет передавать данные непосредственно в его окно (т.е. оба процесса ненадолго «подвиснут»). После того, как в окно Excel будут переданы все данные, книгу можно сохранить в любом поддерживаемом формате, и далее работать как с любой другой книгой Excel, ну и, конечно, использовать как источник данных.
Способ 2. Способ посложнее — команда контекстного меню в интерфейсе: Export — CSV (Экспорт — CSV).
В появившемся диалоговом окне нужно выбрать тип файла — Comma Delimited CSV:
НА ЗАМЕТКУ! CSV (данные в виде простого текста, разделители запятые) — распространенный формат для обмена данных между различными системами и приложениями.
Способ подходит для случаев, когда количество строк в чарте больше чем 65 тысяч и вследствие этого выгрузка напрямую в Excel выполняется чересчур долго.
QV самостоятельно создаст файл формата CSV в указанном расположении, других приложений открывать не будет.
Процесс может ненадолго «подвиснуть».
Получившийся CSV-файл можно загрузить:
- в Excel (на обычный лист через команду «Данные — Получение внешних данных — Из текста» или в модель PowerPivot),
- Access
- и многие другие настольные приложения и системы.
Однако способ нужно применять с осторожностью — он ресурсоемкий по RAM и есть риск того, что процесс QV займет всю доступную оперативную память, а локальная рабочая станция «зависнет». Зато следующий способ лишен этого недостатка.
Способ 3. Продвинутый способ — команда контекстного меню в интерфейсе: Export — QVD (Экспорт — QVD) и последующее преобразование в CSV
Как и в предыдущем способе, команда Экспорт, в типе файла выбрать QlikView Data File QVD:
НА ЗАМЕТКУ! QVD — проприетарный формат хранения данных в системах Qlik, оптимизированный для очень быстрой загрузки и поддерживающий компрессию данных.
Способ подходит для случаев, когда количество строк данных слишком велико для выгрузки их предыдущими способами — сотни тысяч и даже миллионы.
QV самостоятельно создаст файл формата QVD в указанном расположении, других приложений открывать не будет. Операция выполняется достаточно быстро даже на миллионах строк данных, процесс совершенно НЕ ресурсоемкий.
Получившийся QVD-файл можно либо непосредственно загрузить в пользовательское QlikView/Qlik Sense-приложение, либо преобразовать его в CSV с помощью такого простейшего QlikView-скрипта (запускать в локальном QV-приложении, сохраненном в том же расположении что и исходный QVD-файл; процесс также НЕ ресурсоемкий):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
[QVD_Data]: LOAD * From [{filename}.qvd] (qvd) ; STORE [QVD_Data] Into [{filename}.csv] (txt, delimiter is ',') ; |
II. Автоматизированный перенос данных из ассоциативной модели QV в CSV/таблицу СУБД
Такая задача иногда встречается в компаниях, где QlikView является «единым источником правды»: требуется в автоматизированном режиме регулярно передавать «сырые» либо агрегированные/обогащенные/обработанные/вновь порожденные данные из ассоциативной модели приложения QlikView в другую корпоративную систему.
Вот способы, которыми это можно сделать.
Способ 1. Сохранение указанной таблицы модели данных в файл CSV
Любую таблицу модели данных приложения можно сохранить на этапе выполнения скрипта в файл формата CSV с помощью кода, практически аналогичного созданию QVD:
1 2 3 4 5 6 7 8 9 10 11 |
STORE [{tablename}] Into [{filepath}\{filename}.csv] (txt, delimiter is ',') ; |
В качестве filepath нужно указать локальный или сетевой (в формате UNC) ресурс, доступ к которому есть у системы-рецепиента. В качестве filename можно использовать либо статичное название (тогда CSV-файл будет каждый раз перезаписываться), либо использовать Dollar-sign expansion и в название файла ставить суффикс даты-времени создания (тогда каждый раз будет создаваться новый CSV-файл). Случай, когда CSV-файл нужно отправлять на FTP, будет рассмотрен в следующем разделе.
Подавляющее большинство систем умеет работать с данными в формате CSV; для реализации процессов импорта данных нужно обратиться к документации соответствующего ПО.
Способ 2. Передача данных из указанной таблицы модели данных в таблицу СУБД
QlikView в своем развитии затачивался на развитие функций импорта данных из возможно более широкого перечня источников, чего нельзя сказать о функциях экспорта. Задача BI-инструмента – это, все-таки, «интеграция IN»; a «интеграция OUT» — вторична. Хотя Qlik в последние годы уделяет большее внимание этому направлению — Embedded Analytics, API.
Однако даже в привычном QlikView версий 11 и 12 есть встроенная возможность работы «на запись» с другими системами, основанными на СУБД.
Для этого используется команда скрипта (script statement) — SQL, которая позволяет отправить сформированную QlikView SQL-инструкцию к СУБД по открытому ODBC/OLE DB соединению.
Инструкция может включать в себя команды на запись данных в таблицу, вызов хранимой процедуры с параметрами и т.п.; набор возможных действий во многом будет определяться архитектурой конкретной БД.
Примеры передачи данных в таблицу СУБД Oracle
Далее будет рассмотрено несколько примеров передачи данных в таблицу СУБД Oracle на этапе выполнения скрипта QlikView-приложения.
Пример 1. Построчная передача данных
Стандартный SQL-синтаксис предлагает следующую команду для вставки значений в таблицу: INSERT INTO <tablename> VALUES ( <comma-separated list of values> ). Создадим цикл, где количество итераций будет равно количеству строк в таблице данных, и в каждой итерации запустим выполнение SQL-команды.
Ограничением данного способа является низкая производительность — передача сотен тысяч строк может сильно затянуться.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
OLEDB CONNECT To …; /* включение режима Qualify для далее создаваемых таблиц */ QUALIFY * ; /* Эталонная процедура вставки: INSERT INTO qv_testing_task_tmp ( id, syscreatetime, partner_id, prefix_id, destination, remark, test_profile_id, test_type ) VALUES ( qv_testing_task_tmp_seq.nextval, sysdate, :partner_id, :prefix_id, :destination, :remark, :test_profile_id, :test_type ) */ /* Таблица данных для вставки в Oracle */ [Целевая таблица кейсов]: LOAD * Resident [Проверки на критерии Кейсов (fact)] Where /* только отловленные кейсы */ Match( [_Результат Проверки - Кейс есть/нет], 1 ) ; /* цикл с построчной обработкой таблицы */ FOR vIx = 1 to NoOfRows('Целевая таблица кейсов') /* присвоение переменным значений из полей строки таблицы */ LET vStr_partner_id = Peek( 'Целевая таблица кейсов.Partner.ID' , ( vIx - 1 ), 'Целевая таблица кейсов' ); LET vStr_prefix_id = Peek( 'Целевая таблица кейсов.Prefix.ID' , ( vIx - 1 ), 'Целевая таблица кейсов' ); LET vStr_destination = Peek( 'Целевая таблица кейсов.Sys Destination' , ( vIx - 1 ), 'Целевая таблица кейсов' ); LET vStr_remark = Peek( 'Целевая таблица кейсов.Comment' , ( vIx - 1 ), 'Целевая таблица кейсов' ); LET vStr_test_profile_id = Peek( 'Целевая таблица кейсов.TestProfile.ID' , ( vIx - 1 ), 'Целевая таблица кейсов' ); LET vStr_mon_profile_id = Peek( 'Целевая таблица кейсов.Mon.Profile.ID' , ( vIx - 1 ), 'Целевая таблица кейсов' ); LET vStr_test_type = 'ACD'; /* замена на null в случае если строка пустая, добавление кавычек */ LET vStr_partner_id = If( ( Len( vStr_partner_id ) > 0 ) , Chr(39) & vStr_partner_id & Chr(39), 'null' ); LET vStr_prefix_id = If( ( Len( vStr_prefix_id ) > 0 ) , Chr(39) & vStr_prefix_id & Chr(39), 'null' ); LET vStr_destination = If( ( Len( vStr_destination ) > 0 ) , Chr(39) & vStr_destination & Chr(39), 'null' ); LET vStr_remark = If( ( Len( vStr_remark ) > 0 ) , Chr(39) & vStr_remark & Chr(39), 'null' ); LET vStr_test_profile_id = If( ( Len( vStr_test_profile_id ) > 0 ) , Chr(39) & vStr_test_profile_id & Chr(39), 'null' ); 'null' ); LET vStr_mon_profile_id = If( ( Len( vStr_mon_profile_id ) > 0 ) , Chr(39) & vStr_mon_profile_id & Chr(39), 'null' ); LET vStr_test_type = If( ( Len( vStr_test_type ) > 0 ) , Chr(39) & vStr_test_type & Chr(39), TRACE SQL-команда: INSERT INTO qv_testing_task_tmp (id, syscreatetime, partner_id, prefix_id, destination, remark, test_profile_id, test_type, monitoring_profile_id) VALUES (qv_testing_task_tmp_seq.nextval, sysdate, $(vStr_partner_id), $(vStr_prefix_id), $(vStr_destination), $(vStr_remark), $(vStr_test_profile_id), $(vStr_test_type), $(vStr_mon_profile_id)); /* выполнение SQL-команды, передача параметров через dollar-sign expansions */ SQL INSERT INTO qv_testing_task_tmp (id, syscreatetime, partner_id, prefix_id, destination, remark, test_profile_id, test_type, monitoring_profile_id) VALUES (qv_testing_task_tmp_seq.nextval, sysdate, $(vStr_partner_id), $(vStr_prefix_id), $(vStr_destination), $(vStr_remark), $(vStr_test_profile_id), $(vStr_test_type), $(vStr_mon_profile_id)); /* сохранение SQL-команды в таблице QV для последующего контроля */ [SQL Commands]: LOAD 'insert into qv_testing_task_tmp (id, syscreatetime, partner_id, prefix_id, destination, remark, test_profile_id, test_type, monitoring_profile_id) values (qv_testing_task_tmp_seq.nextval, sysdate, $(vStr_partner_id), $(vStr_prefix_id), $(vStr_destination), $(vStr_remark), $(vStr_test_profile_id), $(vStr_test_type), $(vStr_mon_profile_id))' as [SQL Command] AutoGenerate (1) ; NEXT DISCONNECT; |
Пример 2. Пакетная передача данных
Способ подходит для тех случаев, когда количество строк данных велико, и построчная обработка может затянуться на неприемлемое время. Некоторые СУБД (Oracle) предлагают специальные SQL-команды, в которых можно передать значения полей для группы строк.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
/* Эталонная процедура вставки двух строк за раз: INSERT ALL INTO qlick.qv_testnumber_add (PREFIX, TESTNUMBER, REGDATE, TESTNUMBER_TYPE) VALUES (:prefix, :testnumber, sysdate, :testnumber_type) INTO qlick.qv_testnumber_add (PREFIX, TESTNUMBER, REGDATE, TESTNUMBER_TYPE) VALUES (:prefix, :testnumber, sysdate, :testnumber_type) SELECT * FROM dual */ /* генерация и выполнение SQL команд к базе, пакетное добавление по 50 строк в одной команде INSERT ALL INTO VALUES. Более быстрый, чем построчное добавление. */ /* параметр - количество наборов значений в инструкции SQL INSERT ALL (далее упоминается как группа) */ LET vNum_SQLInsertAll_GroupSize = 50; /* добавление поля с номером группы и строки в группе */ [tmp.table01]: NoConcatenate LOAD *, ( Ceil( RowNo() / $(vNum_SQLInsertAll_GroupSize) ) & '|' & ( RowNo() - ( Ceil( RowNo() / $(vNum_SQLInsertAll_GroupSize) ) - 1 ) * $(vNum_SQLInsertAll_GroupSize) ) ) as [SQLInsertAll.GroupNo|NoInGroup] Resident [Целевая таблица] ; DROP Table [Целевая таблица] ; RENAME Table [tmp.table01] to [Целевая таблица] ; /* определение общего количества групп по 50 строк */ LET vNum_MaxSQLInsertAllGroupNo = Ceil( NoOfRows('Целевая таблица') / $(vNum_SQLInsertAll_GroupSize) ); TRACE vNum_MaxSQLInsertAllGroupNo=$(vNum_MaxSQLInsertAllGroupNo); /* цикл для определения состава значений 50 строк для SQL-команды */ /* для каждой из групп */ FOR vIx = 1 to vNum_MaxSQLInsertAllGroupNo LET vSQL_IntoValues = Null(); /* для каждой строки группы */ FOR vJx = 1 to $(vNum_SQLInsertAll_GroupSize) /* флаг существования строки с данным номером в данной группе */ LET vFlag_StringExistsInTable = If( FieldIndex( 'SQLInsertAll.GroupNo|NoInGroup', ( vIx & '|' & vJx ) ) > 0, 1, 0 ); LET vStr_ID = Lookup( 'Целевая таблица.ID', 'SQLInsertAll.GroupNo|NoInGroup', ( vIx & '|' & vJx ), 'Целевая таблица' ); /* замена на null в случае если строка пустая, добавление кавычек */ LET vStr_ID = If( ( Len( vStr_ID ) > 0 ) , Chr(39) & vStr_ID & Chr(39), 'null' ); /* если строка существует в таблице, то подстановка ее значений в SQL-команду */ IF vFlag_StringExistsInTable then LET vSQL_IntoValues = vSQL_IntoValues & ' ' & 'INTO qlick.qv_testnumber_deactivate (id) VALUES' & ' ' & '($(vStr_ID))' ; ENDIF NEXT /* окончательное определение SQL-команды */ SET vSQL_Command = INSERT ALL $(vSQL_IntoValues) SELECT * FROM dual ; /* выполнение SQL-команды*/ SQL $(vSQL_Command) ; /* сохранение SQL-команды в таблице QV для последующего контроля */ [SQL Commands.01]: LOAD '$(vSQL_Command)' as [SQL Command.01] AutoGenerate (1) ; NEXT DROP Field [SQLInsertAll.GroupNo|NoInGroup] ; |
В заключение этой части статьи стоит отметить, что описанные способы реализуются на уровне скрипта приложения QlikView, и, следовательно, автоматизация их регламентного выполнения делается точно также, как и для ETL/конечных аналитических приложений QV — через создание задания (Task) в QV Management Console (QMC).
III. Автоматизированный перенос данных из чартов QlikView в Excel/CSV с помощью NPrinting.
Эта задача аналогична первой — «Ручной перенос данных из чарта QV в Excel/CSV/QVD», но с тем отличием, что выгрузку требуется выполнять автоматически по регламенту.
Самым удобным ее решением в границах ландшафта QV мне представляется использование NPrinting (про него я уже писал статьи на этом блоге, см. ссылки в конце статьи).
У NPrinting есть как собственный Scheduler, так и возможность быть запущенным из соответствующего задания (Task) в QMC, что лично мне представляется более удобным (триггеры в таком случае могут быть настроены на события от других заданий).
Решение задачи здесь будет в несколько шагов:
- В новом проекте NPrinting создается Connection к целевому QV-приложению, настраиваются Filters (например, фильтры на определенные значения в полях, активация указанных Bookmarks, изменение значений Variables);
- Создается Report, для Excel все очевидно и рассмотрено во множестве других статей, а вот для выгрузки в CSV делается по-другому, поэтому приведу несколько скриншотов:
В диалоговом окне Report нужно указать Object ID того чарта, данные из которого требуется выгрузить, и целевое имя CSV-файла (с динамическим формированием суффикса, если необходимо).
3. Создается Report Task, в диалоговом окне на закладке General указывается целевое назначение для файла, на закладке Reports добавляется нужный отчет, и в выпадающем списке Output Format — выбирается CSV.
4. Создается Job, туда включается Report Task и, при необходимости, Reload Task для QV-приложения с преобразованиями формата чисел в CSV. Такое приложение может понадобиться, если исходный чарт в QlikView содержит форматирование чисел в ячейках (пробелы как десятичные разделители, символ «%» для дробных величин).
В таком случае можно создать новое простое QV-приложение, в скрипте которого выполняется загрузка CSV-файла, преобразование значений и повторное сохранение в CSV-файл с форматированием чисел в стандартном формате (способ описан выше в статье). Если CSV будет использоваться только в QlikView/Qlik Sense — это необязательно.
И еще одна интересная фишка: NPrinting может отправлять отчеты (в т.ч. выгрузки в формате CSV) не только на Windows shared folders, но и на FTP — сам QlikView этого сделать бы не смог. На одном из моих проектов это реально пригодилось.
IV. Кейсы
В заключение могу сказать, что описанные задачи и способы их решения – совершенно реальные кейсы, которые возникали на моих проектах. Возможность эффективно интегрировать QlikView в бизнес-процессы и потоки данных, в границах уже развернутого решения и без дополнительных инвестиций – сложно переоценить.
Так, для примера:
- Крупная розничная сеть создала мобильное приложение для сотрудников магазинов, позволяющее мгновенно получить информацию о товаре на полке, просто наведя камеру смартфона на штрихкод. На экран тут же будет выведена информация об остатке товара в данном магазине, дате его последней продажи и уровне сервиса за последний месяц. Эти данные поступают в backend приложения из QlikView, передается примерно 1 млн.строк данных. Что интересно, запросы, сделанные frontend-ом, в backend-е обрабатывает Yandex ClickHouse, open source columnar analytical database, почитайте обязательно!
- Телеком-компания настроила процесс отлова фактов, требующих внимания, в режиме реального времени на основе CDR (Call Detail Record). Так, в системе мастер-данных заводится набор профилей, в которых описываются количественные пороги (thresholds), при превышении которых за указанный период нужно подавать сигнализацию. Профиль может быть привязан на любом уровне детализации – например, только вендор, или вендор/префикс и т.п. и может включать в себя один или несколько количественных показателей для контроля.
QlikView каждые несколько минут агрегирует CDR за указанный период (или несколько периодов) и выявляет случаи для сигнализации, после чего передает в ServiceDesk-систему данные для открытия заявки — для какого среза детализации зафиксирован факт, каковы пороги и их превышение и т.п. Дальше заявка маршрутизируется средствами ServiceDesk ответственному инженеру, и он может приступить к выяснению причин и действиям спустя не более чем 10 минут.
P.S. За рамками данной статьи осталось такое направление интеграции QV с другими системами как QlikView API Automation. На этом блоге на такие темы пишут Степан Мотовилов и Илья Голев — рекомендую их статьи к прочтению (ключевое слово для поиска — PowerShell).
На этом по переносу данных из QlikView на сегодня все.
А вот и обещанные ссылки по работе с NPrinting:
До новых встреч!
Вопрос.. а есть что-нибудь, чтобы по нажатию на кнопку выполнялось бы заполнение SQL таблицы Insert into какими-либо значениями, удовлетворяющими текущую выборку. ?
На ум приходит только вызов внешнего модуля (веб-сервиса или подобного) посредством действия в настройках кнопки (Actions — External), например:
— открытие динамического URL
— запуск *.bat / *.exe файла с параметрами
— запуск макроса QlikView с нужными командами на VBScript
Добрый день, Василий.
Интересная статья. Спасибо.
У меня вопрос к вам. Есть QV с таблицей остатков товара, которая загружена в in-memory самим QV.
Мне нужно для другой ИТ-системы взять от QV эти данные по запросу, например, веб-сервисом. Т.е. QV как источник данных.
Как я могу это сделать ? Варианты c вопросами:
1. Могу ли я обратиться напрямую в in-memory QV и сделать Select нужных мне остатков товара прямо там в памяти ? Если да, то как ?
или
2. Если вариант выше не проходит, то мне нужно обращаться к файлам QV, чтобы сделать Select ?
Если вариант 2, то как быстро он будет работать, если в памяти сидят миллионы строк. Это же дисковые операции, которые нивелируют преимущества QV.
С уважением, Алексей.
Алексей,
1. Инструментария для прямого обращения к in-memory модели QlikView (т.е. к области RAM занимаемой процессом qv.exe) из других приложений/процессов — нет. В противном случае это было бы нарушение принципов безопасности при работе ПО.
2. Некоторые ИТ-системы и продукты поддерживают работу с QVD-файлами (применяются в решениях QlikView как промежуточный слой хранения данных с целью хранения историчности, унификации и переиспользования). Например: EasyMorph, Jedox, Alteryx и т.п. Можете попробовать делать Select с их помощью и далее конвертировать в нужный формат. Производительность такого решения будет определяться дисковой подсистемой и возможностями самого ПО, QlikView как таковой задействован не будет.
Из моего опыта, самым удобным способом автоматизированного экспорта чартов (т.е. результатов агрегаций в режиме реального времени) из пользовательского интерфейса является Qlik NPrinting.
В качестве альтернативы можно создать свое решение с использованием QlikView API Automation.
И можете посмотреть в сторону платформы Qlik Sense, где API намного более богат и дает возможность самых разнообразных интеграций. Такое ответвление как Qlik Core как раз дает возможность использовать ассоциативный движок Qlik как поставщик данных для интегрируемых систем.
Василий, спасибо за ответы.
Еще вопрос — есть 16 млн.строк из которых Qlik строит свой отчет.
Если отчет содержит 200 тыс. строк и 1200 столбцов, то при экспорте такого отчета в csv-файл NPrinting job виснет.
Можете подсказать, есть ли какие-то ограничения у Nprinting по количеству строк или столбцов ?
Работает ли такой экспорт в QV ?
Алексей, первый раз за свою карьеру слышу о том, что кому-то потребовалась нормализованная табличная структура с 1200 столбцами. Насчет жестких ограничений отчетов NPrinting — не слышал, но тысячи столбцов и сотни тысяч строк как объект для экспорта — звучит демонически. Делаю догадку, что это весьма неоптимальное решение. Я бы на вашем месте разделил этого слона на меньшие, проглатываемые куски )))
Василий, дело в том, что Клик строит такой отчет и проблем с этим нету.
Для того чтобы не повторять этот функционал в других системах, была мысль использовать готовые результаты этого отчета как источник данных. Прочитав статью выше, хотели попробовать NPrinting.
Судя по всему столкнулись с ограничением. Придется искать обходной путь.
P.S.
В современном мире больших данных и требованиях к реальному времени по работе с ними, таблица размером 200 тыс. строк и 1200 столбцов не является чем-то сверх выдающимся. Для вашего понимания, строки это товар (SKU), а столбцы это магазины (сеть). Это реальный бизнес-кейс.
Получается, что Клик не тянет реальный бизнес-кейс. Очень жаль.
Алексей, на мой взгляд здесь проблема не в том что «Клик не тянет…», а в том что подход к решению задачи оставляет желать лучшего (ничего личного). Использовать отчет в форме сводной таблицы как носитель для миграции данных из системы в систему — априори не является оптимальным решением. Хотя бы потому, что вы экспоненциально плодите сущности — ведь даже пустоты в такой огромной матрице будут занимать определенный размер и требовать ресурсов. Те же данные, приведенные в нормальную форму (понимайте под этим хоть 3NF, хоть таблицу фактов из схемы-звезды) будут намного более компактными, и в системе-получателе обработать их будет также намного проще, не нужно будет транспонировать.
Да и табличный отчет в его классическом смысле (гуглить «stephen few lookup report») с 1200 столбцами — это издевательство над пользователями и системой, а вовсе никакие не «большие данные», которыми вы хвалитесь.