2013-07-20 3 views
0

Я занимаюсь разработкой сайта аренды автомобиля. У меня есть две таблицы test_tbl_cars и test_reservations.Поисковый запрос Mysql

Я использую поисковый запрос (списаны с Jon Kloske в "How do I approach this PHP/MYSQL query?"):

$sql = mysql_query("SELECT 
    test_tbl_cars.*, 
    SUM(rental_start_date <= '$ddate' AND rental_end_date >= '$adate') AS ExistingReservations 
    FROM test_tbl_cars 
    LEFT JOIN test_reservations USING (car_id) 
    GROUP BY car_id 
    HAVING ExistingReservations = 0"); 

Это дает мне отличные результаты поиска, но test_tbl_cars таблица содержит много автомобилей, которые в любой момент поиска возвращает несколько одного и того же автомобиля модель как доступная.

Как я могу отфильтровать запрос, чтобы получить одну из каждой модели?

+3

использовать предложение WHERE для фильтрации –

+1

как насчет замены GROUP BY car_id по GROUP BY car_id, car_model или независимо от вашего поля модели – user1914292

+0

Какой из них вы хотите? – Strawberry

ответ

0

Используйте окрености пункт

$sql = mysql_query("SELECT 
DISTINCT test_tbl_cars.model, test_tbl_cars.*, 
SUM(rental_start_date <= '$ddate' AND rental_end_date >= '$adate') AS ExistingReservations 

ИЗ test_tbl_cars LEFT JOIN test_reservations ИСПОЛЬЗОВАНИЕ (car_id) GROUP BY car_id ИМЕЯ ExistingReservations = 0");

0

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

Так что проблема, с которой вы сталкиваетесь, заключается в том, что в другом вопросе каждая комната имела уникальный идентификатор, и это были уникальные номера, которые люди интересовались бронированием. Здесь вы расширяете концепцию бронируемого элемента до пула предметов определенного класса (в данном случае, модели автомобиля).

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

Итак, во-первых, позволяет начать получать список автомобилей с количеством конфликтующих оговорок (в соответствии с обновлением на мой другой ответ):

(я буду использовать запрос для этих примеров в качестве отправной точки , но обратите внимание, вы действительно должны использовать подготовленные заявления, или, по крайней мере, вылетающих функций, поставляемых с драйвером БД для двух параметров вы проходящими)

SELECT car_id, model_id, SUM(IF(rental_id IS NULL, 0, rental_start_date <= '$ddate' AND rental_end_date >= '$adate')) AS ConflictingReservations 
FROM test_tbl_cars 
LEFT JOIN test_reservations USING (car_id) 
GROUP BY car_id 

Это будет возвращать одну строку в car_id давая вам номер модели , а также количество оговорок, которые конфликтуют с диапазоном дат e указано (0 или более).

Теперь, когда мы спрашивали об отдельных автомобилях (а не только о доступных моделях автомобилей), мы могли бы ограничить и упорядочить результаты с помощью «HAVING ConflictingReservations = 0 ORDER BY model_id» или что-то в этом роде.

Но, если мы хотим получить список наличия ~ ~ моделей, мы должны выполнить дополнительную группировку этих результатов, чтобы получить окончательный ответ:

SELECT model_id, COUNT(*) AS TotalCars, SUM(ConflictingReservations = 0) AS FreeCars, CAST(IFNULL(GROUP_CONCAT(IF(ConflictingReservations = 0, car_id, NULL) ORDER BY car_id ASC), '') AS CHAR) AS FreeCarsList 
FROM (
    SELECT car_id, model_id, SUM(IF(rental_id IS NULL, 0, rental_start_date <= '$ddate' AND rental_end_date >= '$adate')) AS ConflictingReservations 
    FROM test_tbl_cars 
    LEFT JOIN test_reservations USING (car_id) 
    GROUP BY car_id 
) AS CarReservations 
GROUP BY model_id 

Вы заметите, все мы 're - группировка исходного запроса с помощью model_id, а затем использование агрегатных функций, чтобы получить нам model_id, количество всех автомобилей, которые у нас есть у этой модели, количество бесплатных автомобилей этой модели, которые мы имеем, которые мы достигаем, подсчитывая все раз автомобиль имеет нулевое ConflictingReservations и, наконец, симпатичный маленький SQL, который возвращает запятую список car_ids бесплатных автомобилей (в случае, если это было необходимо!)

Быстрое слово о производительности: все левые соединения, групповые байты и подзапросы могут сделать этот запрос очень медленным. Хорошей новостью является внешняя группа, которая должна обрабатывать только столько строк, сколько у вас есть автомобили, поэтому она не должна замедляться, пока вы не получите очень большое количество автомобилей. Однако внутренний запрос объединяет две таблицы (которые могут выполняться довольно быстро с индексами), а затем группируются по всему набору, выполняя функции в каждой строке. Это может стать довольно медленным, особенно по мере увеличения количества резервирований и автомобилей. Чтобы облегчить это, вы можете использовать пункты предложения для внутреннего запроса и объединить их с соответствующими индексами, чтобы уменьшить количество предметов, которые вы проверяете. Существуют и другие трюки, которые вы можете использовать, чтобы перенести сравнение дат начала и окончания в условие соединения, но это тема для другого дня :)

И, наконец, как всегда, если есть неправильные кромки, ошибки, неправильные синтаксис, что угодно - дайте мне знать, и я отредактирую, чтобы исправить!

Смежные вопросы