она состоит из чисел {1.0.2.0,4.2 ....} и заголовков {a1 ... a_n}, {b1...b_m} по краям. Заголовки строчек и столбцов тоже нужно где-то хранить и лучше всего в ArrayList
Эту хрень еще называют шахматной ведомостью или кросс-отчетом. Я ее делал таким образом: 1) метаданные заголовков по X,Y - список описаний каждого заголовка, хранятся в том порядке, в котором группируются. В описании имя поля, формат и прочее по мелочи, типа "кастомная функция форматирования" 2) метаданные ячеек. список описаний каждого поля отображаемого в ячейке на пересечении. тоже - имя поля, формат, иногда функция аггрегирования. 3) данные заголовков: как и в предложенной модели, список списков 4) данные ячеек: как и в предложенной модели, Map из пары координат в список значений полей ячейки
упс. у этой схемы есть изъян. записи заголовков должны быть отсортированы в определенном порядке. это можно сделать только когда все записи прочитаны, т.е. прочитан весь ResultSet. но если мы потом их отсортируем, то индексы в Map станут неправильными, на них-то сортировка не распространяется...
Сейчас загляну в код. Я там что-то мудрил с правильной сортировкой. Да, я делал еще более злым образом, оказывается. У меня на вход генератора отчетов передается три итератора - для значений X, для значений Y и для ячеек. Первые два нужны(но не обязательны) чтобы некоторые ячейки показывались даже если для них нету данных в списке ячеек. А в качестве координат используются не индексы в массивах значений X и Y, а сами эти значения, специальным образом отформатированные, чтобы сортировались в правильном порядке. Т.е. при заполнении из итератора одновременно заполняются и заголовки и ячейки, сортировка не портится.
Или, например, продажи товаров по регионам. Строки - товары, а столбцы - регионы. Но регионы - это тоже таблица, которая может меняться, так что количество столбцов неизвестно. Вот типа этого - http://www.basegroup.ru/deductor/screenshots/olap/cross_table/
По п. 1 и 2 - вариантов, видимо нет. А вот с 4-м вопрос: при рисовании таблички это-ж надо каждый индекс искать в мэпе... Как-то не быстро получается. Может для 4 - тоже массивчики использовать - вида ArrayList ? (3 тогда не нужен) Да, и может быть заменить ArrayList на обычный массив, если число полей всё-таки известно в момент заполнения всего хозяйства? Конечно, если таблица по большей части пустая, то памяти много отъест... Зато никаких поисков по мапу.
А COUNT() вызвать проблемно? Тут надо думать что быстрее - один раз вызвать каунт или х-з сколько раз заниматься копированием памяти внутри ArrayList-а.
Comments 18
то можно сделать просто двухмерный массив.
Или вариант 1 + два массива типа стринг для заголовков.
Reply
Reply
а вот это не понял, поясните плиз
Reply
| b1 | b2 | ...|b_m
-----------------------
a_1 | 1.0| 2.0|
-----------------------
a_2 | 4.2| 10|
-----------------------
a_n | 3 | 0 |
она состоит из чисел {1.0.2.0,4.2 ....} и заголовков {a1 ... a_n}, {b1...b_m} по краям. Заголовки строчек и столбцов тоже нужно где-то хранить и лучше всего в ArrayList
Reply
Reply
Reply
Я ее делал таким образом:
1) метаданные заголовков по X,Y - список описаний каждого заголовка, хранятся в том порядке, в котором группируются. В описании имя поля, формат и прочее по мелочи, типа "кастомная функция форматирования"
2) метаданные ячеек. список описаний каждого поля отображаемого в ячейке на пересечении. тоже - имя поля, формат, иногда функция аггрегирования.
3) данные заголовков: как и в предложенной модели, список списков
4) данные ячеек: как и в предложенной модели, Map из пары координат в список значений полей ячейки
Reply
SELECT x_name, y_name, sum(value)
FROM ...
GROUP BY x_name, y_name
ORDER BY x_name, y_name
P.S. это не значит что нужно его использовать.
Reply
у этой схемы есть изъян.
записи заголовков должны быть отсортированы в определенном порядке.
это можно сделать только когда все записи прочитаны, т.е. прочитан
весь ResultSet.
но если мы потом их отсортируем, то индексы в Map
станут неправильными, на них-то сортировка не распространяется...
Reply
Да, я делал еще более злым образом, оказывается.
У меня на вход генератора отчетов передается три итератора - для значений X, для значений Y и для ячеек. Первые два нужны(но не обязательны) чтобы некоторые ячейки показывались даже если для них нету данных в списке ячеек.
А в качестве координат используются не индексы в массивах значений X и Y, а сами эти значения, специальным образом отформатированные, чтобы сортировались в правильном порядке. Т.е. при заполнении из итератора одновременно заполняются и заголовки и ячейки, сортировка не портится.
Reply
(The comment has been removed)
но M, N динамические (это раз)
каждый заголовок не строка, а запись (несколько полей)
пример -
[категория]
[товар]
[дата] [клиент] [сумма заказа]
аггрегирующие ячейки?
вообще да, есть
но данной структуре это должно быть по барабану
Reply
Или, например, продажи товаров по регионам. Строки - товары, а столбцы - регионы. Но регионы - это тоже таблица, которая может меняться, так что количество столбцов неизвестно. Вот типа этого - http://www.basegroup.ru/deductor/screenshots/olap/cross_table/
PowerBuilder умел сам такие таблицы строить.
Reply
А вот с 4-м вопрос: при рисовании таблички это-ж надо каждый индекс искать в мэпе... Как-то не быстро получается.
Может для 4 - тоже массивчики использовать - вида ArrayList ? (3 тогда не нужен)
Да, и может быть заменить ArrayList на обычный массив, если число полей всё-таки известно в момент заполнения всего хозяйства?
Конечно, если таблица по большей части пустая, то памяти много отъест... Зато никаких поисков по мапу.
Reply
см. выше
неизвестна размерность, пока не прочитан ResultSet
Reply
Тут надо думать что быстрее - один раз вызвать каунт или х-з сколько раз заниматься копированием памяти внутри ArrayList-а.
Reply
Leave a comment