SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 28.03.2011 10:06:04

Supremum
Участник
Зарегистрирован: 28.03.2011
Сообщений: 6

"пакет включенных минут" несколькими запросами, возможно ли?

Заранее извиняюсь, если повтор, но поиском не нашел ничего похожего.

Имеем, упрощенно, таблицу, в которой хранится детализация звонков за календарный месяц:

CREATE TABLE IF NOT EXISTS `detail` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `client_id` bigint(20) DEFAULT NULL COMMENT 'ID Клиента',
  `timestamp` timestamp NOT NULL COMMENT 'Время звонка',
  `dec_duration` decimal(7,2) NOT NULL DEFAULT '0.00' COMMENT 'Длительность звонка',
  `cost` decimal(7,2) NOT NULL COMMENT 'Стоимость звонка',
  PRIMARY KEY (`id`),
  KEY `client_id` (`client_id`)
) ENGINE=MyISAM COMMENT='Детализация' AUTO_INCREMENT=1;

Необходимо каждому `client_id` изменить (обнулить) `cost` первых звонков с начала календарного месяца, сумма `dec_duration` которых <= 100.
Так называемый, "пакет включенных минут".

Сейчас мне приходится это делать руками на языке.

Неактивен

 

#2 28.03.2011 17:57:58

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: "пакет включенных минут" несколькими запросами, возможно ли?

Напишите программу, которая это будет делать для каждого человека: простого
хорошего способа нет (хотя бы потому что не понятно, что делать с одним един-
ственным звонком на 102 минуты).

Неактивен

 

#3 29.03.2011 10:36:13

Supremum
Участник
Зарегистрирован: 28.03.2011
Сообщений: 6

Re: "пакет включенных минут" несколькими запросами, возможно ли?

Программа-то есть, просто количество клиентов > 10k и лавинообразно увеличивается.
Расчетом стоимости пограничного звонка пока готов пожертвовать.

Неактивен

 

#4 29.03.2011 17:45:03

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: "пакет включенных минут" несколькими запросами, возможно ли?

Даже если Вы готовы пожертвовать стоимостью пограничного звонка, всё равно
одним запросом это не сделаешь smile База данных умеет или группировать, или не
группировать.

Если, например, денормализовать данные, и писать помимо длины звонка еще и
суммарную длину звонков, то тогда можно всё свести к одному запросу. Но всё
равно прийдется где-то исправлять программу (в этом случае — в месте, где пи-
шется информация о звонке).

Неактивен

 

#5 31.03.2011 09:38:24

Supremum
Участник
Зарегистрирован: 28.03.2011
Сообщений: 6

Re: "пакет включенных минут" несколькими запросами, возможно ли?

Что-ж, спасибо за ответ.
По крайней мере не буду тратить время на решение неразрешимой задачки smile

Неактивен

 

#6 05.04.2011 11:43:45

Supremum
Участник
Зарегистрирован: 28.03.2011
Сообщений: 6

Re: "пакет включенных минут" несколькими запросами, возможно ли?

Продолжаем разговор.

Запихнуть во временную таблицу список `id` из `detail`, собраный следующим селектом:
SELECT * FROM (SELECT `id`, `client_id`, `timestamp`, `dec_duration`, (SELECT SUM(`dec_duration`) FROM `detail` WHERE `timestamp` <= `t1`.`timestamp` AND `client_id` = `t1`.`client_id`) `dur_sum` FROM `detail` `t1` ORDER BY `timestamp`) `t2` WHERE `t2`.`dur_sum` <= 100;

Далее UPDATE `detail`, __tmp_table SET `detail`.`cost` = 0 WHERE `detail`.`id` =  __tmp_table.id;

Следующий шаг: Помогите описать UPDATE с использованием вышеуказанного селекта без временной таблицы.

PS.
Задачка, на самом деле, оказалась стандартной и имеет название "Накопительные итоги"
http://www.sql-tutorial.ru/ru/book_running_totals.html

Отредактированно Supremum (05.04.2011 11:46:24)

Неактивен

 

#7 05.04.2011 12:06:21

Supremum
Участник
Зарегистрирован: 28.03.2011
Сообщений: 6

Re: "пакет включенных минут" несколькими запросами, возможно ли?

Собственно, я теперь уже и сам, наверно:

UPDATE `detail` INNER JOIN (SELECT `id`, `client_id`, `timestamp`, `dec_duration`, (SELECT SUM(`dec_duration`) FROM `detail` WHERE `timestamp` <= `t1`.`timestamp` AND `client_id` = `t1`.`client_id`) `dur_sum` FROM `detail` `t1` ORDER BY `timestamp`) `t2` ON `t2`.`id` = `detail`.`id` SET `detail`.`cost` = 0 WHERE `t2`.`dur_sum` <= 100;

И, отбросив лишнее:
UPDATE `detail` INNER JOIN (SELECT `id`, (SELECT SUM(`dec_duration`) FROM `detail` WHERE `timestamp` <= `t1`.`timestamp` AND `client_id` = `t1`.`client_id`) `dur_sum` FROM `detail` `t1` ORDER BY `timestamp`) `t2` ON `t2`.`id` = `detail`.`id` SET `detail`.`cost` = 0 WHERE `t2`.`dur_sum` <= 100;

Остается открытым вопрос о порганичном звонке:
Его стоимость необходимо расчитать из исходной стоимости, уменьшив ёё пропорционально количеству остатка бесплатных минут пакета, пришедшихся на этот звонок.
Был бы благодарен за подсказку.

Неактивен

 

#8 05.04.2011 17:04:03

Supremum
Участник
Зарегистрирован: 28.03.2011
Сообщений: 6

Re: "пакет включенных минут" несколькими запросами, возможно ли?

А вот и тот самый невозможный один запрос, который полностью решает задачу с учетом пограничной минуты:

UPDATE `detail` INNER JOIN (SELECT `t2`.`id`, IFNULL(`t2`.`cost`*(GREATEST(0, `t2`.`dur_sum` - 100)/`t2`.`dec_duration`), 0) AS `new_cost` FROM (SELECT `id`, `dec_duration`, `cost`, (SELECT SUM(`dec_duration`) FROM `detail` WHERE `timestamp` <= `t1`.`timestamp` AND `client_id` = `t1`.`client_id`) `dur_sum` FROM `detail` `t1` ORDER BY `timestamp`) `t2` WHERE `t2`.`dur_sum` <= 100 UNION SELECT `t2`.`id`, IFNULL(`t2`.`cost`*(GREATEST(0, `t2`.`dur_sum` - 100)/`t2`.`dec_duration`),0) AS `new_cost` FROM (SELECT `id`, `dec_duration`, `cost`, (SELECT SUM(`dec_duration`) FROM `detail` WHERE `timestamp` <= `t1`.`timestamp` AND `client_id` = `t1`.`client_id`) `dur_sum` FROM `detail` `t1` ORDER BY `timestamp`) `t2` WHERE `t2`.`dur_sum` > 100 GROUP BY `client_id`) `t3` ON `t3`.`id` = `detail`.`id` SET `detail`.`cost` = `t3`.`new_cost`;

Да, пограничная минута минимум в 2 раза увеличивает накладные расходы, но тем не менее - это решение.
Всем пожалуйста.

Отредактированно Supremum (05.04.2011 17:08:01)

Неактивен

 

#9 08.04.2011 21:29:48

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: "пакет включенных минут" несколькими запросами, возможно ли?

Аааа, какой страшный зверь. Я бы сделал кучкой маленьких простых
запросов. Потому что когда Вам нужно будет исправить в этом ошибку
(или что-то поменять) — я Вам не завидую smile

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson