![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Помогите пожалуйста правильно составить запрос. [D6, Sybase]
r9000 © (2006-12-25 06:10:00)Добрый день!
Изменяю запрос в котором изначально выводятся все записи с кодами AnalyticType=15 and AnalyticCode=2. Мне необходимо чтобы в результирующий набор не включались записи с кодами AnalyticType=15 и AnalyticCode=2,если промежуток между датами для записей с этим кодами был меньше или равен 180 дням.
SELECT RecAn.AnalyticCode ,
AnCode.AnCodeValue ,
count(C.Recipient)
FROM
PlacesOfWork A ,
Companies,Recipients C,
PensionContracts P,
RecipientAccounts R,
RecipientAnalyticCodes RecAn,
AnalyticCodesByDate AnCode
where A.Company = Companies.Company
and A.Recipient =C.Recipient
and C.Recipient =P.Recipient
and P.RecipientAccount=R.RecipientAccount
and RecAn.Recipient=C.Recipient
and (AnCode.AnalyticType=RecAn.AnalyticType and AnCode.AnalyticCode=RecAn.AnalyticCode )
group by AnCode.AnalyticType,RecAn.AnalyticCode,AnCode.AnCodeValue
Правильно ли я написал запрос? Он таким должен быть?
SELECT RecAn.AnalyticCode ,
AnCode.AnCodeValue ,
count(C.Recipient)
FROM
PlacesOfWork A ,
Companies,Recipients C,
PensionContracts P,
RecipientAccounts R,
RecipientAnalyticCodes RecAn,
AnalyticCodesByDate AnCode
where A.Company = Companies.Company
and A.Recipient =C.Recipient
and C.Recipient =P.Recipient
and P.RecipientAccount=R.RecipientAccount
and RecAn.Recipient=C.Recipient
and (AnCode.AnalyticType=RecAn.AnalyticType and AnCode.AnalyticCode=RecAn.AnalyticCode )
---это то что я вставил
and not exists (select * from RecipientAnalyticCodes RecAn,PensionContracts P,
RecipientAccounts R where RecAn.Recipient=C.Recipient and AnalyticType=15 and AnalyticCode=2
and P.RecipientAccount=R.RecipientAccount and C.Recipient =P.Recipient
and datediff(day,R.LastOperDate,'09.01.2006' )<=180)
---это то что я вставил
group by AnCode.AnalyticType,RecAn.AnalyticCode,AnCode.AnCodeValue
r9000 (2006-12-26 12:22:00) [1]Да получается я связь одну забыл RecAn.Recipient = P.Recipient
Спасибо.
ЮЮ (2006-12-26 09:52:00) [2]RecAn.Recipient=C.Recipient
C.Recipient = P.Recipient
это, по сути, фильтры, а не связи таблиц
Из RecipientAnalyticCodes возьмутся все записи текущего реципиента, и из RecipientAccounts возьмутся все записи текущего реципиента и тупо перемножатся. В результате имели
08.05.05 15 3
01.06.06 15 2
и человек не должен был исключаться из списка, а получим
08.05.05 15 3
08.05.05 15 2
01.06.06 15 3
01.06.06 15 2
и мы его исключим из-за второй строки
Тогда как должен выглядеть правильный?
select *
from
RecipientAnalyticCodes RecAn
JOIN PensionContracts P ON RecAn.Recipient = P.Recipient
JOIN RecipientAccounts R ON P.RecipientAccount = R.RecipientAccount
where
RecAn.Recipient = C.Recipient and
AnalyticType=15 and
AnalyticCode=2 and
datediff(day,R.LastOperDate,'09.01.2006' )<=180)
r9000 (2006-12-26 06:59:00) [3]А разве связка C.Recipient не связывает ее с таблицей Р C.Recipient = P.Recipient , а от этой связи P.RecipientAccount=R.RecipientAccount
r9000 (2006-12-26 06:55:00) [4]Так вы считаете
запрос
select *
from
RecipientAnalyticCodes RecAn,
PensionContracts P,
RecipientAccounts R
where
RecAn.Recipient=C.Recipient and
AnalyticType=15 and
AnalyticCode=2 and
P.RecipientAccount=R.RecipientAccount and
C.Recipient = P.Recipient and
datediff(day,R.LastOperDate,'09.01.2006' )<=180)
неправильным?
Тогда как должен выглядеть правильный?
ЮЮ (2006-12-26 06:50:00) [5]---это то что я вставил
and not exists (select * from RecipientAnalyticCodes RecAn,PensionContracts P,
RecipientAccounts R where RecAn.Recipient=C.Recipient and AnalyticType=15 and AnalyticCode=2
and P.RecipientAccount=R.RecipientAccount and C.Recipient =P.Recipient
and datediff(day,R.LastOperDate,'09.01.2006' )<=180)
---это то что я вставил
Внимательно глянув на код ещё, обратил внимание, что RecAn никак не связана с таблицами P и R. Поздравляю!
Именно таких ошибок и можно избежать, отказавшись от неявной связи в пользу явной.
select *
from
RecipientAnalyticCodes RecAn,
PensionContracts P,
RecipientAccounts R
where
RecAn.Recipient=C.Recipient and
AnalyticType=15 and
AnalyticCode=2 and
P.RecipientAccount=R.RecipientAccount and
C.Recipient = P.Recipient and
datediff(day,R.LastOperDate,'09.01.2006' )<=180)
r9000 (2006-12-26 06:14:00) [6]Да, как вы пишете в пункте г)
не включаются показания у тех работников, у которых
есть показания (AnalyticType=15 and AnalyticCode=2) полученные ранее 08.07.2005.
Это то что я и хотел получить. Спасибо.
ЮЮ (2006-12-26 03:32:00) [7]and RecAn.AnalyticType=46
and RecAn.AnalyticCode<>17
and not exists (select * from RecipientAnalyticCodes RecAn where RecAn.Recipient=C.Recipient and AnalyticType=15 and AnalyticCode=3)
and exists (select * from RecipientAnalyticCodes RecAn where RecAn.Recipient=C.Recipient and AnalyticType=48 and AnalyticCode=1)
and not exists (select * from RecipientAnalyticCodes RecAn where RecAn.Recipient=C.Recipient and AnalyticType=15 and AnalyticCode=4)
Теперь ещё и это всплыло !!!
Тогда еще раз в чем неправилен мой запрос:
Я даже не знаю что тебе надо получить этим запросом, а ты спрашиваешь, что непроавильно? Тебе что, на русский перевести то, что ты наваял в запросе?
Найти разные значения AnCode.AnCodeValue и их количество для RecAn.AnalyticType=46 и RecAn.AnalyticCode<>17 имевших место до 09.01.2006 для работников по последнему (до 09.01.2006) месту работы.
Не всключать показания тех работников, у которых:
а) есть показания (AnalyticType=15 and AnalyticCode=3) независимо от даты таких показаний
б) есть показания (AnalyticType=48 and AnalyticCode=1) независимо от даты таких показаний
в) есть показания (AnalyticType=15 and AnalyticCode=4) независимо от даты таких показаний
г) есть показания (AnalyticType=15 and AnalyticCode=2) полученные ранее 08.07.2005
Если это именно то, что тебе надо, то запрос правильный.
>
> Поэтому возможно еще, что если мы вставим
> not (
> (RecAn.AnalyticType = 15) and (RecAn.AnalyticCode = 2)
> and
> (datediff(day, R.LastOperDate, '09.01.2006' )<= 180)
> )
> в данный запрос, результат будет неправильным.
Это вставлять не нужно, т.к. запрос выбирает данные только с RecAn.AnalyticType=46, и эта добавканикак не повлияет на выборку
r9000 (2006-12-25 13:02:00) [8]В 20 сообщении ты пишешь:
>В запросе (1) по определению останется записей не меньше чем в (2).
>Т.к. в (1) ты потеряешь только тех реципиентов, у которых есть "давние" >данные (datediff(day,R.LastOperDate,'09.01.2006' )<=180),
Я бы сказал потеряю данные которые удовлетворяют 3 условиям
(RecAn.AnalyticType = 15) and (RecAn.AnalyticCode = 2) and
(datediff(day, R.LastOperDate, '09.01.2006' )<= 180). Я так тебя понял?
Тогда еще раз в чем неправилен мой запрос:
SELECT convert(varchar(20),"46") as Company,
RecAn.AnalyticCode as "РНН" ,
AnCode.AnCodeValue as "Наименование",
null as "Код Подразделения",
null as "Наименование Подразделения",
count(C.Recipient) as "Количество"
FROM
PlacesOfWork A ,
Companies,Recipients C,
PensionContracts P,
RecipientAccounts R,
RecipientAnalyticCodes RecAn,
AnalyticCodesByDate AnCode
where A.Company = Companies.Company
and A.Recipient =C.Recipient
and C.Recipient =P.Recipient
and P.RecipientAccount=R.RecipientAccount
and RecAn.Recipient=C.Recipient
and (AnCode.AnalyticType=RecAn.AnalyticType and AnCode.AnalyticCode=RecAn.AnalyticCode )
and P.Closed=0
and P.OpenDate <= '09.01.2006'
and R.CreditRest>0
and RecAn.AnalyticType=46
and RecAn.AnalyticCode<>17
and not exists (select * from RecipientAnalyticCodes RecAn where RecAn.Recipient=C.Recipient and AnalyticType=15 and AnalyticCode=3)
and exists (select * from RecipientAnalyticCodes RecAn where RecAn.Recipient=C.Recipient and AnalyticType=48 and AnalyticCode=1)
and not exists (select * from RecipientAnalyticCodes RecAn where RecAn.Recipient=C.Recipient and AnalyticType=15 and AnalyticCode=4)
---это то что я вставил
and not exists (select * from RecipientAnalyticCodes RecAn,PensionContracts P,
RecipientAccounts R where RecAn.Recipient=C.Recipient and AnalyticType=15 and AnalyticCode=2
and P.RecipientAccount=R.RecipientAccount and C.Recipient =P.Recipient
and datediff(day,R.LastOperDate,'09.01.2006' )<=180)
---это то что я вставил
and A.PlacesID = (SELECT Max(B.PlacesID)
FROM PlacesOfWork B where B.Recipient=A.Recipient and B.BeginDate<='09.01.2006' GROUP BY B.Recipient)
group by AnCode.AnalyticType,RecAn.AnalyticCode,AnCode.AnCodeValue
order by RecAn.AnalyticCode
r9000 (2006-12-25 12:14:00) [9]Да еще запрос данный я сократил немного. Вообще он выглядит так:
SELECT convert(varchar(20),"46") as Company,
RecAn.AnalyticCode as "РНН" ,
AnCode.AnCodeValue as "Наименование",
null as "Код Подразделения",
null as "Наименование Подразделения",
count(C.Recipient) as "Количество"
FROM
PlacesOfWork A ,
Companies,Recipients C,
PensionContracts P,
RecipientAccounts R,
RecipientAnalyticCodes RecAn,
AnalyticCodesByDate AnCode
where A.Company = Companies.Company
and A.Recipient =C.Recipient
and C.Recipient =P.Recipient
and P.RecipientAccount=R.RecipientAccount
and RecAn.Recipient=C.Recipient
and (AnCode.AnalyticType=RecAn.AnalyticType and AnCode.AnalyticCode=RecAn.AnalyticCode )
and P.Closed=0
and P.OpenDate <= '09.01.2006'
and R.CreditRest>0
and RecAn.AnalyticType=46
and RecAn.AnalyticCode<>17
and not exists (select * from RecipientAnalyticCodes RecAn where RecAn.Recipient=C.Recipient and AnalyticType=15 and AnalyticCode=3)
and exists (select * from RecipientAnalyticCodes RecAn where RecAn.Recipient=C.Recipient and AnalyticType=48 and AnalyticCode=1)
and not exists (select * from RecipientAnalyticCodes RecAn where RecAn.Recipient=C.Recipient and AnalyticType=15 and AnalyticCode=4)
and A.PlacesID = (SELECT Max(B.PlacesID)
FROM PlacesOfWork B where B.Recipient=A.Recipient and B.BeginDate<='09.01.2006' GROUP BY B.Recipient)
group by AnCode.AnalyticType,RecAn.AnalyticCode,AnCode.AnCodeValue
order by RecAn.AnalyticCode
Поэтому возможно еще, что если мы вставим
not (
(RecAn.AnalyticType = 15) and (RecAn.AnalyticCode = 2) and
(datediff(day, R.LastOperDate, '09.01.2006' )<= 180)
)
в данный запрос, результат будет неправильным.
И Recipient может иметь одновременно несколько разных записей AnalyticType,AnalyticCode поэтому может быть еще данное условие не
может подходить.
ЮЮ (2006-12-25 12:08:00) [10]Из того что ты сказал следует
что запрос (1) должен дать одинаковый результат с запросом (2).
Если ты сделал такие выводы, то я то тут причем.
В запросе (1) по определению останется записей не меньше чем в (2).
Т.к. в (1) ты потеряешь только тех реципиентов, у которых есть "давние" данные (datediff(day,R.LastOperDate,'09.01.2006' )<=180), а в (2) потеряешь всех, у кого есть какие либо данные с AnalyticType=15 and AnalyticCode=2.
Извини, но пока не сделаешь нормального анализа, предложенного [14]
Перед тем, как считать Count, полезно посмотреть на сами записи:
SELECT
RecAn.AnalyticCode ,
AnCode.AnCodeValue ,
datediff(day, R.LastOperDate, '09.01.2006' ) as Diff ,
*
FROM
...
без GROUP BY
и выполни запросы как с условием, так и без. Их и сравнивай, анализируя, что в столбце Diff
считаю вести дискуссию бесполезной тратой времени.
r9000 (2006-12-25 11:36:00) [11]Из того что ты сказал следует
что запрос
SELECT RecAn.AnalyticCode ,
AnCode.AnCodeValue ,
count(C.Recipient)
FROM
PlacesOfWork A ,
Companies,Recipients C,
PensionContracts P,
RecipientAccounts R,
RecipientAnalyticCodes RecAn,
AnalyticCodesByDate AnCode
where A.Company = Companies.Company
and A.Recipient =C.Recipient
and C.Recipient =P.Recipient
and P.RecipientAccount=R.RecipientAccount
and RecAn.Recipient=C.Recipient
and (AnCode.AnalyticType=RecAn.AnalyticType and AnCode.AnalyticCode=RecAn.AnalyticCode )
---это то что я вставил
and not exists (select * from RecipientAnalyticCodes RecAn,PensionContracts P,
RecipientAccounts R where RecAn.Recipient=C.Recipient and AnalyticType=15 and AnalyticCode=2
and P.RecipientAccount=R.RecipientAccount and C.Recipient =P.Recipient
and datediff(day,R.LastOperDate,'09.01.2006' )<=180)
---это то что я вставил
group by AnCode.AnalyticType,RecAn.AnalyticCode,AnCode.AnCodeValue
должен дать одинаковый результат с запросом
SELECT RecAn.AnalyticCode ,
AnCode.AnCodeValue ,
count(C.Recipient)
FROM
PlacesOfWork A ,
Companies,Recipients C,
PensionContracts P,
RecipientAccounts R,
RecipientAnalyticCodes RecAn,
AnalyticCodesByDate AnCode
where A.Company = Companies.Company
and A.Recipient =C.Recipient
and C.Recipient =P.Recipient
and P.RecipientAccount=R.RecipientAccount
and RecAn.Recipient=C.Recipient
and (AnCode.AnalyticType=RecAn.AnalyticType and AnCode.AnalyticCode=RecAn.AnalyticCode )
---это то что я вставил
and not exists (select * from RecipientAnalyticCodes RecAn,PensionContracts P,
RecipientAccounts R where RecAn.Recipient=C.Recipient and AnalyticType=15 and AnalyticCode=2
and P.RecipientAccount=R.RecipientAccount and C.Recipient =P.Recipient
)
---это то что я вставил
group by AnCode.AnalyticType,RecAn.AnalyticCode,AnCode.AnCodeValue
а это не так в первом запросе в некоторых группировках получается большее количество записей.
ЮЮ (2006-12-25 10:37:00) [12]Ты так и будешь на кофейной гуще гадать?
Выполни подзапрос, что в not Exist(). (1)
теперь свой, только со *, без count и group by. И найди там хоть одну строку для реципиентов из (2). Нашел? То-то.
и вы забыли что связки P.RecipientAccount=R.RecipientAccount and C.Recipient =P.Recipient связывают ее с таблицей RecipientAccounts R.
Но они никак не связаны с RecAn.AnalyticCode и AnCode.AnCodeValue. А это значит:
Пусть для реципиента найдена запись с AnalyticType<>15 или AnalyticCode<>2.
Но она не будет включена в выборку, если у этого же реципиента есть хотя бы одна запись, которую ты хочешь исключить. В подзапросе на Exist нет никакого анализа текущих значений RecAn.AnalyticCode и AnCode.AnCodeValue. А если добавить, то в exist подзапросе получишь полный аналог самого запроса. И зачем? Чтобы сервер для каждой записи основного запроса выполнял этот подзапрос, вместо того, чтобы просто отсеять лишние записи?
r9000 (2006-12-25 10:16:00) [13]Так в моем же запросе есть кроме AnalyticType=15 and AnalyticCode=2
двух условий третье условие and datediff(day,R.LastOperDate,'09.01.2006' )<=180 и вы забыли что связки P.RecipientAccount=R.RecipientAccount and C.Recipient =P.Recipient связывают ее с таблицей RecipientAccounts R.
ЮЮ (2006-12-25 09:56:00) [14]
> Он вродепо результату дает более правильное количество
>
Сначала ответь какие неправильные строки были в запросе из [14]
Скажите а мой запрос разве неправилен
Неправилен. При наличии хоть одной записи, удовлетворяющей условию
AnalyticType=15 and AnalyticCode=2
and P.RecipientAccount=R.RecipientAccount and C.Recipient =P.Recipient
никакая запись об этом реципиенте вообще не попадет в статистику, т.к. связка подзапрос с запросом идет только по одному полю RecAn.Recipient=C.Recipient.
Такие подзапросы тяжелы для любого сервера.
r9000 (2006-12-25 09:46:00) [15]Скажите а мой запрос разве неправилен
SELECT RecAn.AnalyticCode ,
AnCode.AnCodeValue ,
count(C.Recipient)
FROM
PlacesOfWork A ,
Companies,Recipients C,
PensionContracts P,
RecipientAccounts R,
RecipientAnalyticCodes RecAn,
AnalyticCodesByDate AnCode
where A.Company = Companies.Company
and A.Recipient =C.Recipient
and C.Recipient =P.Recipient
and P.RecipientAccount=R.RecipientAccount
and RecAn.Recipient=C.Recipient
and (AnCode.AnalyticType=RecAn.AnalyticType and AnCode.AnalyticCode=RecAn.AnalyticCode )
---это то что я вставил
and not exists (select * from RecipientAnalyticCodes RecAn,PensionContracts P,
RecipientAccounts R where RecAn.Recipient=C.Recipient and AnalyticType=15 and AnalyticCode=2
and P.RecipientAccount=R.RecipientAccount and C.Recipient =P.Recipient
and datediff(day,R.LastOperDate,'09.01.2006' )<=180)
---это то что я вставил
group by AnCode.AnalyticType,RecAn.AnalyticCode,AnCode.AnCodeValue
Он вроде по результату дает более правильное количество
ЮЮ (2006-12-25 08:57:00) [16]
> Кстати, нужно отсечь записи у которых разница <= 180
> для записей у которых
> RecAn.AnalyticType = 15 and RecAn.AnalyticCode = 2
not (
(RecAn.AnalyticType = 15) and (RecAn.AnalyticCode = 2) and
(datediff(day, R.LastOperDate, '09.01.2006' )<= 180)
)
если (RecAn.AnalyticType <> 15) или (RecAn.AnalyticCode <> 2) ,
то выражение в скобках будет ложь и запись останется в выборке.
>
> то по результату он ничем не отличается от запроса
Перед тем, как считать Count, полезно посмотреть на сами записи:
SELECT
RecAn.AnalyticCode ,
AnCode.AnCodeValue ,
datediff(day, R.LastOperDate, '09.01.2006' ) as Diff ,
*
FROM
...
без GROUP BY
и выполни запросы как с условием, так и без. Их и сравнивай, анализируя, что в столбце Diff
r9000 (2006-12-25 08:37:00) [17]Кстати, нужно отсечь записи у которых разница <= 180
для записей у которых
RecAn.AnalyticType = 15 and RecAn.AnalyticCode = 2
а не для всех записей, т.к.
могут быть записи с различной аналитикой, например:
RecAn.AnalyticType = 15 and RecAn.AnalyticCode = 3 и т.д.
И если сделать запрос типа вашего
SELECT RecAn.AnalyticCode ,
AnCode.AnCodeValue ,
count(C.Recipient)
FROM
PlacesOfWork A ,
Companies,Recipients C,
PensionContracts P,
RecipientAccounts R,
RecipientAnalyticCodes RecAn,
AnalyticCodesByDate AnCode
where A.Company = Companies.Company
and A.Recipient =C.Recipient
and C.Recipient =P.Recipient
and P.RecipientAccount=R.RecipientAccount
and RecAn.Recipient=C.Recipient
and (AnCode.AnalyticType=RecAn.AnalyticType and AnCode.AnalyticCode=RecAn.AnalyticCode )
not (
(RecAn.AnalyticType = 15) and (RecAn.AnalyticCode = 2) and
(datediff(day, R.LastOperDate, '09.01.2006' )<= 180)
)
group by AnCode.AnalyticType,RecAn.AnalyticCode,AnCode.AnCodeValue
то по результату он ничем не отличается от запроса
SELECT RecAn.AnalyticCode ,
AnCode.AnCodeValue ,
count(C.Recipient)
FROM
PlacesOfWork A ,
Companies,Recipients C,
PensionContracts P,
RecipientAccounts R,
RecipientAnalyticCodes RecAn,
AnalyticCodesByDate AnCode
where A.Company = Companies.Company
and A.Recipient =C.Recipient
and C.Recipient =P.Recipient
and P.RecipientAccount=R.RecipientAccount
and RecAn.Recipient=C.Recipient
and (AnCode.AnalyticType=RecAn.AnalyticType and AnCode.AnalyticCode=RecAn.AnalyticCode )
group by AnCode.AnalyticType,RecAn.AnalyticCode,AnCode.AnCodeValue
а это неправильно я проверил
r9000 (2006-12-25 08:13:00) [18]А разве в моем запросе сделано неправильно?
ЮЮ (2006-12-25 07:58:00) [19]Т.е. абсолютно все записи раньше 13.07.05 для данного реципиента, сколько бы их не было. И каждая запись в сумму входит единицей?
Я бы просто отобрал нужные записи в WHERE. (Перкместив условия связи таблиц оттуда туда, где им положено быть):
SELECT
RecAn.AnalyticCode ,
AnCode.AnCodeValue ,
count(C.Recipient)
FROM
PlacesOfWork A
JOIN Companies ON A.Company = Companies.Company
JOIN Recipients C ON A.Recipient = C.Recipient
JOIN PensionContracts P ON C.Recipient = P.Recipient
JOIN RecipientAccounts R ON P.RecipientAccount = R.RecipientAccount
JOIN RecipientAnalyticCodes RecAn ON RecAn.Recipient = C.Recipient
JOIN AnalyticCodesByDate AnCode ON
(AnCode.AnalyticType = RecAn.AnalyticType) and
(AnCode.AnalyticCode = RecAn.AnalyticCode )
WHERE
not (
(RecAn.AnalyticType = 15) and (RecAn.AnalyticCode = 2) and
(datediff(day, R.LastOperDate, '09.01.2006' )<= 180)
)
GROUP BY
AnCode.AnalyticType, RecAn.AnalyticCode, AnCode.AnCodeValue
Кстати, таблицы PlacesOfWork, Companies и PensionContracts в этом запросе совсем не нужны.
r9000 (2006-12-25 07:27:00) [20]ну да здесь я немного ошибся с этой записью
Да на дату 09.01.2006 меня интересуют записи раньше 13.07.05 ,т.к.
разница превышает 180 дней
после 09.01.2006 не интересуют, т.к. например 09.01.2006 -10.01.2006
будет -1, что меньше 180 дней и т.д.
в интервале (09.01.2006 - 180) не интересуют