Конференция "Базы" » SQL-запрос посещения [IB6.x, Firebird]
 
  • zorik © (20.10.09 23:24) [0]
    Есть таблица посещений (код клиента, дата визита):

    CREATE TABLE VISIT_HISTORY(
     ID_CLIENT  INTEGER NOT NULL,
     VISIT_DATE DATE NOT NULL
    );

    Можно ли составить запрос тех клиентов, кто не посещал в эти дни. Именно запрос, а не процедуру (процедуру я сделаю). Тоесть надо взять все даты из истории посещений, всех клиентов и вывести тех, кого в который день небыло.

    Просто интересно стало есть ли такая возможнось. БД Firebird. Если нет, то сделаю хранимкой, но все же чисто из интереса
  • Германн © (21.10.09 01:36) [1]
    А разве процедура не есть запрос?
  • Омлет (21.10.09 04:20) [2]
    Декартово произведение таблицы уникальных клиентов с таблицей уникальных клиентов, оставив только тех, кого в конкретный день не было.
  • Омлет (21.10.09 04:21) [3]
    > таблицы уникальных клиентов с таблицей уникальных клиентов

    Пардон, пересечение клиентов с датами, конечно.
  • Кщд (21.10.09 07:22) [4]
    >Омлет   (21.10.09 04:21) [3]
    а если такой даты нет в visit_history?)
  • Sergey13 © (21.10.09 08:39) [5]
    > [0] zorik ©   (20.10.09 23:24)
    > Есть таблица посещений

    А таблица клиентов есть? Если есть, то NOT EXISTS клиентов в посещениях вернет тебе прогульщиков.
  • zorik © (21.10.09 09:20) [6]
    Да, таблица клиентов есть. Но все-равно, надо передавать параметр - дату. Кщд   (21.10.09 07:22) [4] был прав. Че то я перемудрил с вопросом. Сори )))

    select
     id_client
    from clients
    where id_client not in (select id_client from visit_history where date_visit=:adate)
  • zorik © (21.10.09 09:25) [7]

    > Германн ©   (21.10.09 01:36) [1]

    Я име ввиду без конструкций типа "for select... suspend" и т.д., присущим процедурам. А то кажется, что я их использую там, где без них можна было б и обойтись
  • Виталий Панасенко (21.10.09 15:00) [8]
    если версия ФБ поддерживает execute block, то можно и без ХП..:-)
  • palva © (21.10.09 15:29) [9]
    А так нельзя?

    SELECT DISTINCT A.ID_CLIENT FROM VISIT_HISTORY A
    LEFT JOIN VISIT_HISTORY B ON A.ID_CLIENT=B.ID_CLIENT AND B.VISIT_DATE=<yourdate>
    WHERE B.VISIT_DATE IS NULL

  • zorik © (21.10.09 17:11) [10]

    > palva ©   (21.10.09 15:29) [9]

    не знаю, попробую
  • Кщд (22.10.09 07:10) [11]
    >palva ©   (21.10.09 15:29) [9]
    теперь представим, что в таблице visit_history несколько миллионов записей, что вовсе не удивительно при обширной клиентской базе и высокой частоте посещений...

    в этих предположениях актуальнее:

    select g.id, g.name
    from client g
    where not exists (select null
                                 from visit_history vh2
                                 where vh2.id_client = g.id
                                             and vh2.visit_date = :dt
                                  )



    если посещение гарантированно одно на дату по клиенту, то ещё и уникальный индекс на пару "id_client-visit_date"
  • palva © (22.10.09 09:05) [12]
    Здесь ничего не могу ни возразить, ни согласиться. Эффективность запросов для меня темный лес. Возможно, анализатор запросов приведет оба варианта к одной и той же схеме. Хотя мне всегда казалось, что из общих соображений объединение всегда эффективнее многократного подзапроса. А у вас ведь подзапрос будет выполняться для каждой записи, то есть несколько миллионов раз. Кроме того, где-то потерялся DISTINCT.

    Если заботиться об эффективности, то лично я делал бы процедуру. Сначала отобрал бы уникальных клиентов, а потом проверял EXISTS. DISTINCT, примененный на раннем этапе помог бы уменьшить число подзапросов. Хотя возможно оптимизатор движка SQL сам бы обнаружил такую возможность.
  • Кщд (22.10.09 09:37) [13]
    >palva ©   (22.10.09 09:05) [12]
    >Возможно, анализатор запросов приведет оба варианта к одной и той же схеме
    это не так
    оптимизаторы не настолько умны, чтобы включать или исключать таблицы из запроса)

    >объединение всегда эффективнее многократного подзапроса
    в данном случае, самообъединение таблицы-миллионника гораздо хуже прохода по таблице клиентов с подзапросами, посаженными на индекс

    >Кроме того, где-то потерялся DISTINCT
    в нем нет необходимости

    >Если заботиться об эффективности, то лично я делал бы процедуру
    эффективнее здесь использовать запрос
  • palva © (22.10.09 12:05) [14]

    > >Кроме того, где-то потерялся DISTINCT
    > в нем нет необходимости

    А, так у вас отдельная таблица клиентов? Извините, не увидел, что вы анализируете другую задачу.

    > >Если заботиться об эффективности, то лично я делал бы процедуру
    > эффективнее здесь использовать запрос

    Ну раз задачи разные, то сравнивать бессмысленно.
  • Кщд (22.10.09 15:01) [15]
    >palva ©   (22.10.09 12:05) [14]
    >А, так у вас отдельная таблица клиентов? Извините, не увидел, что вы анализируете другую задачу.
    отдельная таблица у автора, что не слишком явно видно из zorik ©   (20.10.09 23:24)  и абсолютно точно в zorik ©   (21.10.09 09:20) [6]

    >Ну раз задачи разные, то сравнивать бессмысленно.
    да, Ваш вариант никогда не покажет, что клиент не приходил, если его нет в visit_history - так что мы с Вами, действительно, решали разные задачи
    какую именно решали Вы - пока не ясно)
  • palva © (22.10.09 19:55) [16]

    > какую именно решали Вы - пока не ясно)

    Задачу, поставленную при открытии ветки.
  • Кщд (23.10.09 07:51) [17]
    >palva ©   (22.10.09 19:55) [16]
    нежелание читать ветку не дает права на советы, ставящие "колом" сервер
    дальнейшее обсуждение бессмысленно
    всего
 
Конференция "Базы" » SQL-запрос посещения [IB6.x, Firebird]
Есть новые Нет новых   [134435   +33][b:0][p:0.001]