Лучший способ сделать сводную таблицу в SQLite? - PullRequest
1 голос
/ 03 августа 2011

Я использую C # и SQLite для нарезки больших объемов данных, и мне часто нужно отображать свои данные в форме сводной таблицы. Я легко могу сделать свои сводные динамические, используя C # для создания команды SQL из другого запроса, но я до сих пор не могу решить, какой способ сделать это самостоятельно, поэтому я хотел бы услышать некоторые мнения по этому вопросу от программистов, имеющих более мне ..

Я имею в виду три метода. Допустим, у нас есть простая таблица с именем tData с тремя столбцами: «row» представляет номер строки этих данных, «col» представляет номер столбца, а «val» представляет значение.

Ортодоксальный метод - использовать выражения CASE:

SELECT
      row,
      sum(CASE col WHEN 1 THEN val END) AS col1,
      sum(CASE col WHEN 2 THEN val END) AS col2,
      sum(CASE col WHEN 3 THEN val END) AS col3
FROM tData
GROUP BY row

Однако я подумал, что может быть быстрее, если я угроблю операторы CASE и использую логическое выражение непосредственно для значения, используя тот факт, что true == 1 и false == 0:

SELECT
      row,
      sum((col=1)*val) AS col1,
      sum((col=2)*val) AS col2,
      sum((col=3)*val) AS col3
FROM tData
GROUP BY row

Я подозреваю, что этот метод должен быть быстрее, поскольку выражение CASE должно иметь некоторые накладные расходы, но я не совсем уверен.

Третий метод немного сложнее: он использует JOIN для выполнения поворота:

SELECT
      rows.row,
      col1.valSum AS col1,
      col2.valSum AS col2,
      col3.valSum AS col3
FROM
    (SELECT row FROM tData GROUP BY row) AS rows
LEFT JOIN
    (SELECT row,sum(val) AS valSum FROM tData WHERE col=1 GROUP BY row) AS col1
    ON rows.row=col1.row
LEFT JOIN
    (SELECT row,sum(val) AS valSum FROM tData WHERE col=2 GROUP BY row) AS col2
    ON rows.row=col2.row
LEFT JOIN
    (SELECT row,sum(val) AS valSum FROM tData WHERE col=3 GROUP BY row) AS col3
    ON rows.row=col3.row

Да, эти соединения имеют серьезные издержки, но из моего ограниченного опыта при работе с большими таблицами реализации SQL могут выполнять простые операции фильтрации групп и сумм гораздо быстрее, чем операции пользовательских манипуляций с данными в каждой строке. и это более чем компенсирует эти накладные расходы. Проблема заключается в том, что такого рода операторы SQL сложнее генерировать, поскольку каждый столбец в операторе появляется в двух местах - один раз в предложении fields и один раз в предложении FROM, а не просто в предложении fields, как первые два метода , Кроме того, мне нужно быть осторожным со всеми именами этих временных таблиц.

Итак, есть ли мнения?

Ответы [ 2 ]

1 голос
/ 03 августа 2011

Я ожидал бы, что подход с оператором case будет выполняться быстрее, чем столько групповых соединений и соединений с вашей таблицей, сколько в рассматриваемом столбце различных значений. Первая интенсивно использует процессор, а вторая - диск. Например. если ваше значение столбца, которое должно стать заголовком столбца, содержит день недели, у вас будет семь сводных столбцов и семь select-groupbys. Это может быть дорого; это будет зависеть от размера таблицы.

0 голосов
/ 03 августа 2011

Похоже, вы используете дизайн EAV , который делает необходимым объединение строк в столбцы.При правильном проектировании реляционной базы данных вы бы не использовали EAV.Столбцы будут столбцами, и вам не нужно будет поворачиваться.

Тем не менее, я понимаю, что EAV иногда является меньшим из зол, и это популярный дизайн, когда нужно хранить «расширяемый» наборАтрибуты в базе данных.

Самый эффективный способ вернуть данные - забыть о выполнении сводки в SQL.Просто извлеките свои атрибуты в виде нескольких строк для каждого заданного значения row:

SELECT row, col, val FROM tData WHERE row = ...

Затем напишите код в своем приложении C #, чтобы перебрать результирующий многострочный набор результатов.Создайте новый объект для каждого отдельного row.Установите для поля col объекта значение val.Затем продолжите извлечение следующей строки результата запроса.

Это имеет преимущества:

  • Запрос прост в написании.Только три столбца для именования в списке выбора, нет необходимости в псевдонимах столбцов.
  • Запрос для СУБД невысок для выполнения.Нет GROUP BY, нет самостоятельных объединений и т. Д.
  • Все еще поддерживает расширяемое преимущество дизайна EAV.На самом деле его проще расширять, потому что когда вы добавляете новые логические столбцы к своим данным, вам не нужно переписывать ваш SQL-запрос.
...