Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

SQL-запрос посещения [IB6.x, Firebird]


zorik ©   (2009-10-20 23:24:00) 

Есть таблица посещений (код клиента, дата визита):

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

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

Просто интересно стало есть ли такая возможнось. БД Firebird. Если нет, то сделаю хранимкой, но все же чисто из интереса


Кщд   (2009-10-23 07:51:00) [1]

>palva ©   (22.10.09 19:55) [16]
нежелание читать ветку не дает права на советы, ставящие "колом" сервер
дальнейшее обсуждение бессмысленно
всего


palva   (2009-10-22 19:55:00) [2]


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

Задачу, поставленную при открытии ветки.


Кщд   (2009-10-22 15:01:00) [3]

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

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


palva   (2009-10-22 12:05:00) [4]


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

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

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

Ну раз задачи разные, то сравнивать бессмысленно.


Кщд   (2009-10-22 09:37:00) [5]

>palva ©   (22.10.09 09:05) [12]
>Возможно, анализатор запросов приведет оба варианта к одной и той же схеме
это не так
оптимизаторы не настолько умны, чтобы включать или исключать таблицы из запроса)

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

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

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


palva   (2009-10-22 09:05:00) [6]

Здесь ничего не могу ни возразить, ни согласиться. Эффективность запросов для меня темный лес. Возможно, анализатор запросов приведет оба варианта к одной и той же схеме. Хотя мне всегда казалось, что из общих соображений объединение всегда эффективнее многократного подзапроса. А у вас ведь подзапрос будет выполняться для каждой записи, то есть несколько миллионов раз. Кроме того, где-то потерялся DISTINCT.

Если заботиться об эффективности, то лично я делал бы процедуру. Сначала отобрал бы уникальных клиентов, а потом проверял EXISTS. DISTINCT, примененный на раннем этапе помог бы уменьшить число подзапросов. Хотя возможно оптимизатор движка SQL сам бы обнаружил такую возможность.


Кщд   (2009-10-22 07:10:00) [7]

>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"


zorik   (2009-10-21 17:11:00) [8]


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

не знаю, попробую


palva   (2009-10-21 15:29:00) [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


Виталий Панасенко   (2009-10-21 15:00:00) [10]

если версия ФБ поддерживает execute block, то можно и без ХП..:-)


zorik   (2009-10-21 09:25:00) [11]


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

Я име ввиду без конструкций типа "for select... suspend" и т.д., присущим процедурам. А то кажется, что я их использую там, где без них можна было б и обойтись


zorik   (2009-10-21 09:20:00) [12]

Да, таблица клиентов есть. Но все-равно, надо передавать параметр - дату. Кщд   (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)


Sergey13   (2009-10-21 08:39:00) [13]

> [0] zorik ©   (20.10.09 23:24)
> Есть таблица посещений

А таблица клиентов есть? Если есть, то NOT EXISTS клиентов в посещениях вернет тебе прогульщиков.


Кщд   (2009-10-21 07:22:00) [14]

>Омлет   (21.10.09 04:21) [3]
а если такой даты нет в visit_history?)


Омлет   (2009-10-21 04:21:00) [15]

> таблицы уникальных клиентов с таблицей уникальных клиентов

Пардон, пересечение клиентов с датами, конечно.


Омлет   (2009-10-21 04:20:00) [16]

Декартово произведение таблицы уникальных клиентов с таблицей уникальных клиентов, оставив только тех, кого в конкретный день не было.


Германн   (2009-10-21 01:36:00) [17]

А разве процедура не есть запрос?


Наверх

Титульная страница Поиск, карта сайта Написать письмо