[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Выборка из нескольких таблиц
Гость_Алексей
Добрый вечер господа!
Хочу обратиться к Вам за помощью в одном вопросе.
Задание следующее: есть система регистрации заявок на ремонт оборудования. Поступившая заявка рассматривается и на неё назначается исполнителЬ или исполнителИ.
Т.е своего рода система ХелпДеск…
В достаточно простом варианте я структуру спроектированной БД нарисовал и выглядит она вот так:
user posted image

Т.е таблицы «Сотрудники» и «Заявки» соединить напрямую нельзя ввиду того, что на одну заявку может быть назначено несколько исполнителей, поэтому получается связь «Многие-ко-многим», которую я превращаю в «Один-к-одному» через создание дополнительной таблицы «Исполнители». Такой вариант не новшество и давно для всех известен).
В таблице «Заявки» есть поле «Дата поступления» и «Статус». «Статус» вообще у меня является внешним ключом от другой таблицы, но тут для простоты я сделал его обычным полем. Этот «статус» может принимать значения: 1 – заявка новая, 2 – заявка в очереди (т.е когда на неё назначили сотрудников), 3 – заявка выполнена.

Если я хочу сделать выборку, чтобы для каждого сотрудника из таблицы «Сотрудники»
посчиталось сколько заявок вообще за ним числится, сколько заявок у него в статусе «В очереди» (т.е которые оформлены на него, но которые он пока не выполнил) и сколько заявок он выполнил, то формирую запрос вот такого вида:

SELECT
COUNT( * ) AS total,
SUM( hd_order.id_status =2 ) AS turn,
SUM( hd_order.id_status =3 ) AS made,
hd_employee.lastname
FROM
hd_employee,
hd_performers,
hd_order
WHERE
hd_order.id_order = hd_performers.id_order AND
hd_employee.id_emp = hd_performers.id_emp
GROUP BY hd_employee.lastname
ORDER BY hd_employee.lastname

И получаю вот такой результат:

total turn made lastname
9 3 6 Иванов
4 2 2 Петров
10 4 6 Сидоров
6 3 3 Алексеев
6 4 2 Семёнов

НО, это я сделал выборку вообще всех записей, какие есть в БД, по сути без какого-либо дополнительного условия…
А если я вот, например, захочу сделать такую же выборку, но чтобы еще учитывалась ДАТА ЗАЯВКИ…ну скажем за сегодня….
Тогда если я в условие WHERE допишу:
AND hd_order.date_receipt = NOW()


Он мне вытащит только те записи, которые соответствуют этому условию. НО тут возможна такая ситуация, что «за сегодня» вообще заявок нет, тогда мне сопсна ничего и не вернётся, а я хочу чтобы он всё равно вывел мне всех сотрудников из таблицы «Сотрудники», как в результате выше, но только для всёх них написал НУЛИ, например вот так:

total turn made lastname
0 0 0 Иванов
0 0 0 Петров
0 0 0 Сидоров
0 0 0 Алексеев
0 0 0 Семёнов

Пробовал я в запросе указывать LEFT JOIN и прообвал через всякие IS NULL и прочее – нифига не получилось, поэтому прошу Вашей помощи, как такую задачу можно реализовать?
Заранее спасибо!
P.S. много написал, но старался описать вопрос подробней, чтобы по сто раз не объяснять потом)




Спустя 1 час, 18 минут, 13 секунд (2.04.2012 - 21:09) Гость_Алексей написал(а):
Для тех, кому лень всё читать:
Надо вывести список ВСЕХ Сотрудников независимо от того, были ли у них заявки за заданный период времени или нет...smile.gif

Спустя 3 минуты, 37 секунд (2.04.2012 - 21:12) Игорь_Vasinsky написал(а):
ну тут либо2 запроса - второй после того как после первого ничё не вернулось

либо IF юзать в самом запросе. то есть назначить алияс для выборке и если нуль то второй подзапрос на вывод всех.

как то так.

Спустя 5 минут, 19 секунд (2.04.2012 - 21:17) inpost написал(а):
Запрос к первой таблице, а далее в цикле запросы к двум другим таблицам.

Спустя 2 минуты, 12 секунд (2.04.2012 - 21:20) Игорь_Vasinsky написал(а):
Цитата
а далее в цикле запросы к двум другим таблицам.

ай ай ай...

Спустя 5 минут, 8 секунд (2.04.2012 - 21:25) Гость_Алексей написал(а):
Ну тут как бы можно сделать несложную, но "тупую" выборку, а потом уже в самом ПХП намутить такого, чтобы результат был соответсвующий, но честно признаться так делать не особо охота...

Спустя 5 минут, 32 секунды (2.04.2012 - 21:30) Игорь_Vasinsky написал(а):
ну так вроде операторы ветвления в самом SQL должны быстрей отработать при правильном раскладе - чем обёртка на PHP и тем более запросы к 2м таблицам в цикле.

Спустя 14 минут, 39 секунд (2.04.2012 - 21:45) inpost написал(а):
Игорь_Vasinsky
В цикле будет быстрее работать, чем через LEFT JOIN. smile.gif
В такой среде работаем, что тут сделаешь.

Спустя 1 минута, 51 секунда (2.04.2012 - 21:47) Игорь_Vasinsky написал(а):
если речь о 3х таблицах - то чем алияс на ту в которой даты не гож? вернул ноль - пошёл другой. ну это ИМХО на теории чисто.

Спустя 16 минут, 1 секунда (2.04.2012 - 22:03) Placido написал(а):
Не знаю, как так не получилось через LEFT JOIN.
Примерно так:
SELECT 
COUNT(*) AS total,
SUM(temp.id_status = 2) AS turn,
SUM(temp.id_status = 3) AS made,
hd_employee.lastname
FROM hd_employee
LEFT JOIN
(SELECT
hd_performers.id_emp,
hd_order.id_status
FROM hd_performers
INNER JOIN hd_order
ON hd_order.id_order = hd_performers.id_order
WHERE hd_order.date_receipt = CURDATE()) temp
ON hd_employee.id_emp = temp.id_emp
GROUP BY hd_employee.lastname
ORDER BY hd_employee.lastname

Спустя 1 час, 18 минут, 51 секунда (2.04.2012 - 23:22) Гость_Алексей написал(а):
Placido, да, вот это уже похоже на правду!)
А не получилось у меня через Лефт Джоин потому что неправильно писал)

При Вашем запросе результат такой:

total turn made lastname
1 NULL NULL Иванов
1 NULL NULL Петров
1 NULL NULL Сидоров
1 NULL NULL Алексеев
1 NULL NULL Семёнов

У меня уже, честно признаться, голова кругом идёт от всего этого, половину сейчас не соображаю...почему в колонке Total у всех 1, если по сути дела на СЕГОДНЯ заявок ни у кого нет?!

Спустя 3 минуты, 51 секунда (2.04.2012 - 23:26) Гость_Алексей написал(а):
...или это из соображений программирования что Кол-во начинается с 1, а Сумма с 0 ?...))

Спустя 1 минута, 28 секунд (2.04.2012 - 23:27) Гость_Алексей написал(а):
т.е не кол-во с единицы, а произведение...
Короче я всё, пас, мозги не работают)

Спустя 7 минут, 48 секунд (2.04.2012 - 23:35) Placido написал(а):
Тогда COUNT(*) AS total нужно переместить в подзапрос, а в SELECT вынести temp.total
SELECT 
temp.total,
SUM(temp.id_status = 2) AS turn,
SUM(temp.id_status = 3) AS made,
hd_employee.lastname
FROM hd_employee
LEFT JOIN
(SELECT
COUNT(*) AS total,
hd_performers.id_emp,
hd_order.id_status
FROM hd_performers
INNER JOIN hd_order
ON hd_order.id_order = hd_performers.id_order
WHERE hd_order.date_receipt = CURDATE()) temp
ON hd_employee.id_emp = temp.id_emp
GROUP BY hd_employee.lastname
ORDER BY hd_employee.lastname

Спустя 4 минуты, 31 секунда (2.04.2012 - 23:39) Гость_Алексей написал(а):
Тогда ругается:

#1140 - Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause

Спустя 10 минут, 30 секунд (2.04.2012 - 23:50) Placido написал(а):
Тогда так:

SELECT
COUNT(temp.id_emp) AS total,
SUM(temp.id_status = 2) AS turn,
SUM(temp.id_status = 3) AS made,
hd_employee.lastname
FROM hd_employee
LEFT JOIN
(SELECT
hd_performers.id_emp,
hd_order.id_status
FROM hd_performers
INNER JOIN hd_order
ON hd_order.id_order = hd_performers.id_order
WHERE hd_order.date_receipt = CURDATE()) temp
ON hd_employee.id_emp = temp.id_emp
GROUP BY hd_employee.lastname
ORDER BY hd_employee.lastname

Спустя 17 минут, 20 секунд (3.04.2012 - 00:07) Гость_Алексей написал(а):
Офигеть)
Заработало!)
Placido, ОГРОМНЕЙШЕЕ ВАМ СПАСИБО!:)
Завтра буду разбираться как Вы это реализовали, а то уже мозгам ахтунг пришел)

Спустя 4 часа, 8 минут, 10 секунд (3.04.2012 - 04:15) Игорь_Vasinsky написал(а):
заметьте и без циклов wink.gif , но и без условий в запросе unsure.gif

Спустя 11 часов, 35 минут, 46 секунд (3.04.2012 - 15:51) aleksey_ov написал(а):
Да!
Это говорит о том, что нужно было создать грамотный запрос к базе, что у меня не получалось никак)
Placido, спасибо еще раз Вам большое!)
P.S. чёт не могу Вам плюсануть, наверно сообщений мало тут отправил... ph34r.gif
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.