MySQL добавить итоговый столбец - PullRequest
4 голосов
/ 29 января 2009

Мне нужно запросить эту БД для получения каждой строки, а также СУММУ одного из значений столбца результатов. Я мог бы использовать php для получения итогового значения, но тогда мне нужно было бы запустить два цикла, один для получения итогового значения (которое идет вверху над результатами). Поэтому я бы предпочел, чтобы запрос перехватил его и просто создал «итоговую» строку, но единственный способ, с помощью которого я его получил, - это подзапрос, который по сути повторяет исходный запрос. Есть ли лучший способ?

SELECT 
CONCAT(u.firstname, ' ', u.lastname ) name, u.id, s.description, s.shiftstart, s.shiftend, 
    (SELECT 
    SUM( TIME_TO_SEC( TIMEDIFF( shiftend, shiftstart ) ) ) /3600
    FROM shifts
    WHERE id =  '$user'
    AND DATE( shiftstart )
    BETWEEN '$start'
    AND '$end') total
FROM shifts s
INNER JOIN users u ON ( s.id = u.id )
WHERE s.id = '$user'
AND DATE( shiftstart )
BETWEEN '$start'
AND '$end'
ORDER BY shiftstart

Вышеуказанные работы и выводы:

name        id     description  shiftstart             shiftend               total
Joe User    joeuser    Stuff    2009-01-05 07:45:00    2009-01-05 12:15:00    39.5000
Joe User    joeuser    Stuff    2009-01-05 13:00:00    2009-01-05 17:00:00    39.5000
Joe User    joeuser    Stuff    2009-01-06 07:45:00    2009-01-06 10:45:00    39.5000
Joe User    joeuser    Stuff    2009-01-06 10:45:00    2009-01-06 12:45:00    39.5000
Joe User    joeuser    Stuff    2009-01-06 13:30:00    2009-01-06 14:30:00    39.5000
Joe User    joeuser    Stuff    2009-01-06 14:30:00    2009-01-06 17:00:00    39.5000
Joe User    joeuser    Stuff    2009-01-07 09:45:00    2009-01-07 14:00:00    39.5000
Joe User    joeuser    Stuff    2009-01-07 15:00:00    2009-01-07 17:00:00    39.5000
Joe User    joeuser    Stuff    2009-01-08 08:00:00    2009-01-08 12:15:00    39.5000
Joe User    joeuser    Stuff    2009-01-08 13:15:00    2009-01-08 17:00:00    39.5000
Joe User    joeuser    Stuff    2009-01-09 07:45:00    2009-01-09 10:45:00    39.5000
Joe User    joeuser    Stuff    2009-01-09 11:45:00    2009-01-09 15:15:00    39.5000
Joe User    joeuser    Stuff    2009-01-09 15:15:00    2009-01-09 17:00:00    39.5000

Это то, что мне нужно, но, вероятно, не лучший способ получить его.

Ответы [ 4 ]

5 голосов
/ 29 января 2009

MySQL поддерживает специальный групповой модификатор под названием ROLLUP .

SELECT CONCAT(u.firstname, ' ', u.lastname ) name, u.id, 
  s.description, s.shiftstart, s.shiftend, 
  SUM( TIME_TO_SEC( TIMEDIFF( shiftend, shiftstart ) ) ) /3600 total
FROM shifts s INNER JOIN users u ON ( s.id = u.id )
WHERE s.id = ? AND DATE( shiftstart ) BETWEEN ? AND ?
GROUP BY u.id, s.shiftstart WITH ROLLUP
ORDER BY shiftstart;
3 голосов
/ 29 января 2009

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

Запустите два запроса из вашего кода. Сначала выведите больший набор, затем итоговую строку в любом формате. Ваши запросы будут меньше и проще, ваша производительность улучшится, и вы получите желаемый результат.

Несколько других советов: дисковое пространство дешевое, и большинство таблиц базы данных читаются гораздо чаще, чем пишутся. Установите триггер вставки / обновления (если это возможно в MySQL) для заполнения отдельного столбца вычисляемыми полями, такими как «CONCAT(u.firstname,' ',u.lastname)», и используйте его для запросов. Функции для каждой строки не масштабируются и снижают производительность вашей СУБД по мере увеличения.

0 голосов
/ 29 января 2009

Используйте расширение mysql, предоставленное именно для этой цели, как описано в ответе Билла Карвина (за который я сам проголосовал).

Если бы этого не было, вариант 2 был бы другим оператором SQL: SELECT SUM ...) SQL действительно оптимизирован, чтобы быть чрезвычайно эффективным для такого рода вещей, по сравнению с любыми циклами процедурного кода, которые вы, вероятно, написать.

0 голосов
/ 29 января 2009

Все может быть лучше в сравнении; вопрос в сравнении с чем, верно?

Ключевой вопрос, который вы указали, заключается в том, что вы хотели получить итоговую сумму в верхней части результатов; Crystal Reports и другие приложения управляют этим видом магии с помощью двухпроходного движка. Первый проход получает итоги.

Есть компромиссы с любым решением. Если вы получите отдельную строку «итого», то получающее приложение должно будет либо убрать его из результатов, либо выполнить какой-то другой трюк, чтобы скрыть его.

Одна из возможностей, которая может быть возможной, если вы не пишете для веб-сайта со скоростью 1 миллион посещений в час, состоит в том, чтобы просто сделать 2 вызова - один для дополнительной информации, такой как имя, ОБЩЕЕ время и т. Д., затем для деталей ... Это появляется из запроса, который вы выбираете результаты одного человека.

Мы все для экономии накладных расходов и пропускной способности, но иногда проще просто ...

РЕДАКТИРОВАТЬ: Пакс избил меня до кнопки "сохранить" ... LOL ...

...