ФорумРазработкаБазы данных → Бутерброд из вложенных запросов, не могу прожевать несколько AND и IN подряд.

Бутерброд из вложенных запросов, не могу прожевать несколько AND и IN подряд.

  • armageddance

    Сообщения: 29 Репутация: N Группа: Кто попало

    Spritz Авг. 3, 2011, 12:50 п.п.

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

    category - таблица услуг: name - название услуги, sid - идентификатор услуги.
    sessions - таблица записей: service_id - идентификатор услуги в ней, start_time - время начала оказания услуги, end_time - время окончания оказания услуги, session_id - идентификатор записи.
    client_sessions - таблица связи клиентов и записей. client_id - идентификатор клиента, session_id - идентификатор записи.

    SELECT name FROM category WHERE sid IN
    (
    SELECT DISTINCT service_id FROM sessions WHERE session_id IN
    (
    SELECT session_id FROM sessions WHERE
    (
    (
    start_time<=(SELECT start_time FROM sessions WHERE session_id='$session_id')
    AND end_time>=(SELECT start_time FROM sessions WHERE session_id='$session_id')
    )
    OR
    (
    start_time<=(SELECT end_time FROM sessions WHERE session_id='$session_id')
    AND end_time>=(SELECT end_time FROM sessions WHERE session_id='$session_id')
    )
    OR
    (
    start_time>=(SELECT start_time FROM sessions WHERE session_id='$session_id')
    AND end_time<=(SELECT end_time FROM sessions WHERE session_id='$session_id')
    )
    OR
    (
    start_time<=(SELECT start_time FROM sessions WHERE session_id='$session_id')
    AND end_time>=(SELECT end_time FROM sessions WHERE session_id='$session_id')
    )
    )
    )
    AND session_id<>'$session_id'
    AND session_id IN
    (
    SELECT session_id FROM client_sessions WHERE client_id='$client_id'
    )

    )

    Вот такой запрос возвращает какие-то услуги, но не те, какие нужно вернуть, что-то у него с логикой (со скобками) не так….
  • AlexB

    Сообщения: 4306 Репутация: N Группа: в ухо

    Spritz Авг. 3, 2011, 12:58 п.п., спустя 7 минут 45 секунд

    Я не понял, а нафига третья таблица?
    Что мешает в sessions сразу id клиента писать?
    Спустя 107 сек.
    И еще, открой для себя JOIN
  • armageddance

    Сообщения: 29 Репутация: N Группа: Кто попало

    Spritz Авг. 3, 2011, 1:03 п.п., спустя 4 минуты 45 секунд

    ТО есть, берем $session_id, определяем у нее start_time и end_time, определяем те записи, какие пересекаются по времени с текущей, сравниваем с теми session_id, на которые записан текущий клиент client_id, отнимаем из полученного списка текущую session_id (мы ее итак знаем) и выдаем названия услуг name, на которые есть запись по всем найденным session_id
    Спустя 116 сек.

    Я не понял, а нафига третья таблица?
    Что мешает в sessions сразу id клиента писать?
    Спустя 107 сек.
    И еще, открой для себя JOIN

    Дело в том, что клиентов может быть несколько в одной записи. Групповые записи на услуги. То есть тут связь один ко многому, поэтому заведена таблица client_sessions.
  • AlexB

    Сообщения: 4306 Репутация: N Группа: в ухо

    Spritz Авг. 3, 2011, 1:19 п.п., спустя 16 минут 6 секунд

    SELECT
    C.Name
    FROM
    category as C
    JOIN sessions as S ON S.sid = C.session_id
    JOIN client_sessions as CS USING (session_id)
    WHERE
    CS.cient_id = ид клиента AND здесь условие на пересечение промежутков времени, сам пиши мне лень

    Что-то типа такого, я не отлаживал, главное показал тебе как JOIN работает
  • armageddance

    Сообщения: 29 Репутация: N Группа: Кто попало

    Spritz Авг. 3, 2011, 1:45 п.п., спустя 26 минут 3 секунды

    Разобрался, все правильно на самом деле.
    Только два последних OR в проверке пересечений - лишние. Надо так:

    (
                              start_time<=(SELECT start_time FROM sessions WHERE session_id='$session_id')
                                       AND end_time>=(SELECT start_time FROM sessions WHERE session_id='$session_id')
                              )
    OR
                              (
                              start_time<=(SELECT end_time FROM sessions WHERE session_id='$session_id')
                                       AND end_time>=(SELECT end_time FROM sessions WHERE session_id='$session_id')
                               )
    Спустя 100 сек.

    SELECT
    C.Name
    FROM
    category as C
    JOIN sessions as S ON S.sid = C.session_id
    JOIN client_sessions as CS USING (session_id)
    WHERE
    CS.cient_id = ид клиента AND здесь условие на пересечение промежутков времени, сам пиши мне лень

    Что-то типа такого, я не отлаживал, главное показал тебе как JOIN работает

    Да, в такой форме запрос намного изящнее и проще выглядит, спасибо, поправлю…
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz Авг. 3, 2011, 2:25 п.п., спустя 40 минут 34 секунды

    Да, в такой форме запрос намного изящнее

    изящнее запрос .. эх! он мне уже нравится!
    Сапожник без сапог

Пожалуйста, авторизуйтесь, чтобы написать комментарий!