Задать вопрос
@bighoc
php/javascript developer

Можно ли обойтись одним запросом?

Имееться таблица отпусков работников. В таблице отпусков храниться дата начала отпуска и дата окончания.
Поля таблицы: ид_отпуска, начало_отпуска (DATE), конец_отпуска (DATE), имя_сотрудника

Скажем
Ваня идёт с 7 по 10 число
Ира идёт с 8 по 12 число

Нужно получить статстику типа этой:

6 число - 0 сотрудников в отпуске
7 число - 1 сотрудник в отпуске
8 число - 2 сотрудника в отпуске
9 число - 2 сотрудника в отпуске
10 число - 2 сотрудника в отпуске
11 число - 1 сотрудника в отпуске
12 число - 1 сотрудника в отпуске
13 число - 0 сотрудников в отпуске

Не хотелось бы делать на каждый день отдельный запрос. Думаю можно извартиться както и получить то что нужно, но я пока не придумал как.
Буду благодарен за любые идеи ?
  • Вопрос задан
  • 274 просмотра
Подписаться 1 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 5
нужна таблица с датами (каждая строка таблицы - новый день), если диапазон дат известен, то можно собрать путем SELECT .. UNION SELECT ... и т.д.

вот запрос, который скажет вам в какой день сколько сотрудников отсутствует:
SELECT c.date_time, COUNT(*) as cnt
FROM calendar c -- таблица о которой я написал выше
LEFT JOIN leave_people p ON c.date_time BETWEEN p.start_date AND IFNULL(p.end_date, c.date_time)
GROUP BY c.date_time


здесь IFNULL использовал для тех целей, когда окончание неизвестно, например человек на больничном (для случая, когда в таблице leave_people хранятся не только отпуска, но и больничные и т.д.)
Ответ написан
DmitriyEntelis
@DmitriyEntelis
Думаю за деньги
Мне кажется наиболее рациональное решение - выбрать все данные из Вашей таблицы за нужный период, и за 1 проход цикла в любом ЯП составить требуемую табличку.
Ответ написан
Комментировать
profit
@profit
Разработка | Оптимизация. Telegram: @evzavyalov
табличка с данными
CREATE TABLE `t_otp` (
	`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
	`dt_start` DATE NULL DEFAULT NULL,
	`dt_end` DATE NULL DEFAULT NULL,
	`fio` VARCHAR(50) NULL DEFAULT NULL,
	PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

INSERT INTO `t_otp` (`id`, `dt_start`, `dt_end`, `fio`) VALUES
	(1, '2015-03-07', '2015-03-10', 'Ваня'),
	(2, '2015-03-08', '2015-03-12', 'Ира');


запрос
select concat(tab.date,' число - ', 
       (select count(1) from t_otp where tab.date between dt_start and dt_end)
    , ' сотрудника в отпуске ') abb
  from (
SELECT '2015-03-06' + INTERVAL(CAST(CONCAT(CAST(a.num AS CHAR), CAST(b.num AS CHAR)) AS UNSIGNED)) DAY `date`
 FROM
(SELECT 0 AS num UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS a,
(SELECT 0 AS num UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS b
WHERE '2015-03-06' + INTERVAL(CAST(CONCAT(CAST(a.num AS CHAR), CAST(b.num AS CHAR)) AS UNSIGNED)) DAY <= '2015-03-13'
ORDER BY 1
) tab


результат
2015-03-06 число - 0 сотрудника в отпуске
2015-03-07 число - 1 сотрудника в отпуске
2015-03-08 число - 2 сотрудника в отпуске
2015-03-09 число - 2 сотрудника в отпуске
2015-03-10 число - 2 сотрудника в отпуске
2015-03-11 число - 1 сотрудника в отпуске
2015-03-12 число - 1 сотрудника в отпуске
2015-03-13 число - 0 сотрудника в отпуске


оптимизируйте дальше сами...
Ответ написан
Комментировать
Если в БД хранится именно так в 1 или 2 полях "Ваня идёт с 7 по 10 число" т.е. интервалом то нельзя. То это какая-то странная организация БД. Если там хотя бы 2 числа в двух полях + 1 на имя, например Ваня 7 и 10 то можно запросить все сотрудников где число 1 больше 8 и число 2 меньше 10 получим всех кто в отпуске 9го. О месяце тут ещё у вас нет информации. А если отпуск рваный двумя интервалами?
Ответ написан
@Centrino
Можно обойтись 1 запросом (если данные в колонки Базы хранятся именно та как вы написали), но вам нужно будет перебрать все комбинации и объединить их с помощью OR, делать обрезание строки на кол-во символов после нахождения с и по, присваивать этим значениям аргументы и по этим аргументам делать Group By. Но это ЖОПА, легче сделать нормальную базу!!
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы