Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.08.01;
Скачать: CL | DM;

Вниз

Как исключить лишние записи из SQL-запроса, используя Count?   Найти похожие ветки 

 
alexe   (2004-07-08 13:19) [0]

Здравствуйте! Помогите, пожалуйста, решить следующую проблему.
Есть задача: получить количество договоров для каждого клиента по каждому продукту из БД в Access. Пишу запрос:
SELECT ProductName, ClientName, Count(ContractName)
....
Group by P.ProductName, C.ClientName
В результате получаю количество записей в БД по клиенту и продукту, в которых есть договор, т.е. если клиент брал продукт 10 раз, то получаю количество 10, хотя договор один и тот же.
Нашел функцию Count(Distinct <выражение>), т.е. выбор одной записи из нескольких одинаковых, но она упорно не хочет работать с Access. В SQL-builder написание функции проходит, а на этапе непосредственного выполнения запроса - выдается ошибка.


 
Reindeer Moss Eater ©   (2004-07-08 13:23) [1]

а на этапе непосредственного выполнения запроса - выдается ошибка.

Это очень плохо.
Но скоро это пройдет само собой.

Нашел функцию Count(Distinct <выражение>),

Где ты такое нашел?


 
Reindeer Moss Eater ©   (2004-07-08 13:26) [2]

SELECT ProductName, ClientName, Count(ContractName)
....
Group by P.ProductName, C.ClientName


А условие объединения нам самим домыслить?


 
alexe   (2004-07-08 13:34) [3]

To Reindeer Moss Eater
Функцию нашел в книге Шумакова П.В. "Delphi3 и разработка приложений баз данных".
Привожу полный запрос:
SELECT P.ProductName, C.ClientName, Count(Cnt.ContractName)
FROM CLAIM1 Cl, REPORT1 R, CLIENT1 C, LOAD L, PRODUCT1 P, CONTRACT1 Cnt
WHERE  (R.ReportCode = Cl.ClaimReport)  
  AND  (C.ClientCode = Cl.ClaimContragent)  
  AND  (P.ProductCode = R.ReportProduct)  
  AND  (L.LoadReport = Cl.ClaimReport)  
  AND  (L.LoadLetter = Cl.ClaimLetter)  
  AND  (L.LoadContract = Cnt.ContractCode)  
  AND  ( (R.ReportYear = 2004)  
  AND  (R.ReportMounth = 5) )
Group by P.ProductName, C.ClientName


 
Johnmen ©   (2004-07-08 13:37) [4]

Как именно Count(Distinct <выражение>) не хочет работать ?


 
Reindeer Moss Eater ©   (2004-07-08 13:39) [5]

Убери count и group by.
Получи датасет и посчитай кол-во руками, внимательно глядя на содержимое полей в наборе данных


 
alexe   (2004-07-08 13:53) [6]

To Johnmen
Выдается ошибка для ф-ции Count( distinct Cnt.ContractName):
"Ошибка синтаксиса (пропущен оператор) в выражении запроса "Count( distinct Cnt.ContractName)"".
А если использовать Count( distinct *) с добавлением в Group by Cnt.ContractName, то "Лишняя скобка ) в выражении запроса Count( distinct *)."

To Reindeer Moss Eater
Ручной подсчет не выход, т.к. это всего лишь подзадача, а загромаждать лишними циклами программу не есть хорошо в плане времени ее выполнения, т.к. анализируемых записей может быть до нескольких десятков тысяч :((


 
sniknik ©   (2004-07-08 13:54) [7]

обьеденение неявное т.е. inner join, т.е. выдаст все пересечения. а по условию нужно left join делать, или right.


 
sniknik ©   (2004-07-08 13:56) [8]

ручной подсчет тебе для проверки данных посоветовали, а окончательно естественно нужно запрос правильно составить.


 
Ильш ©   (2004-07-08 13:59) [9]

а вложенные запросы как же??? прям заплакаль я....


 
alexe   (2004-07-08 14:01) [10]

То sniknik
Что-то я не понимаю, как мне поможет изменение внутреннего соединения на внешнее, если убирая Count, я получаю корректную выборку?


 
alexe   (2004-07-08 14:04) [11]

То Ильш
А можно поконкретнее?


 
sniknik ©   (2004-07-08 14:05) [12]

убирая Count убираеш и ContractName из обьеденения.
но вообше я не настаиваю, надо смотреть на данных я чисто теоретически.


 
Johnmen ©   (2004-07-08 14:06) [13]

>alexe

Запрос в части COUNT(DISTINCT <column specification>) соответствует стандарту SQL92.
Если проблемы именно из-за такого каунта, то это проблема Аксеса.


 
Ильш ©   (2004-07-08 14:07) [14]

select P.ProductName, C.ClientName, (select count(*) from CONTRACT1 Cnt) as kolvo from tbl...
типа такого


 
Reindeer Moss Eater ©   (2004-07-08 14:07) [15]

Убери count и group by.

Получи датасет и посчитай кол-во руками, внимательно глядя на содержимое полей в наборе данных

Во первых убедишься, что count тебе не врет
Во вторых поймешь каких условий в объединении нехватает.


 
alexe   (2004-07-08 14:15) [16]

То sniknik
Если убрать ContractName, то получиться список продукт+клиент, а как добраться до договора? Ситуация такова, что нужно получить из выборки продукт1/клиент1/договор1; продукт1/клиент1/договор2 и т.д. продукт1/клиент1/кол-во отгрузок по договору1; продукт1/клиент1/кол-во отгрузок по договору2 и т.д., причем, желательно, не создавая промежуточную таблицу для хранения выборки продукт1/клиент1/договор1; продукт1/клиент1/договор2 и т.д.


 
Reindeer Moss Eater ©   (2004-07-08 14:18) [17]

т.е. если клиент брал продукт 10 раз, то получаю количество 10, хотя договор один и тот же.

... ClientName, Count(ContractName)

Ну и что же ты хочешь?
В десяти записях есть информация о том, что клиент брал один и тот же продукт.
Count(ContractName) тебе честно об этом сообщает.


 
alexe   (2004-07-08 14:31) [18]

То Johnmen
А эта проблема Access"a "врожденная" или конкретной копии, или Access97 ?

To Reindeer Moss Eater
Count не врет. Без него выдается:
продукт1/клиент1/договор1
продукт1/клиент1/договор1
с ним: продукт1/клиент1/2, а должен/нужно (по моим понятиям :)) продукт1/клиент1/1


 
alexe   (2004-07-08 14:36) [19]

То Reindeer Moss Eater
С этим я согласен, что правильно выдается 10! А мне нужно исключить из подсчета 9 лишних, что я и пытаюсь сделать :))
Раскопал даже формат ф-ции Count(Distinct <...>), а в таком виде она не работает.


 
Johnmen ©   (2004-07-08 14:37) [20]

>alexe   (08.07.04 14:31) [18]

Узнай сам. :)
SELECT COUNT(DISTINCT ProductName)
FROM PRODUCT1

и
SELECT ProductCode, COUNT(DISTINCT ProductName)
FROM PRODUCT1
GROUP BY ProductCode


 
Reindeer Moss Eater ©   (2004-07-08 14:37) [21]

продукт1/клиент1/1

select distinct(продукт,клитент) .....

И не надо никаких count


 
Reindeer Moss Eater ©   (2004-07-08 14:40) [22]

А мне нужно исключить из подсчета 9 лишних, что я и пытаюсь сделать :))

Ты пытаешься получить строго детерминированный результат с помощью запроса.
Зачем тебе count, если ты точно знаешь, что он должен вернуть единицу и ничего больше?

тебе нужны все существующие уникальные пары продукт - клиент.
и накакие count тебе не нужны


 
sniknik ©   (2004-07-08 14:40) [23]

> продукт1/клиент1/договор1;
> продукт1/клиент1/договор2

тогда тут групировка не нужна, или наоборот нужно вкючить в нее и договор. в показаном у тебя только по продукт1/клиент1.

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


 
sniknik ©   (2004-07-08 14:44) [24]

> и накакие count тебе не нужны
насколько понял нужно, но немного не в том контексте как сейчас делается

нужно
продукт1/клиент1/договор1/кол-во отгрузок по договору1
продукт1/клиент1/договор2/кол-во отгрузок по договору2
...
в таком виде колво должно считатся.


 
Reindeer Moss Eater ©   (2004-07-08 14:46) [25]

Он в колонке count всегда ждет 1.
И расстривается когда там > 1

не нужен ему count.


 
sniknik ©   (2004-07-08 14:49) [26]

> Он в колонке count всегда ждет 1.
потому что "договор" пропушено, договор у него должен быть всегда 1 а вот привязанный к этому договору отгрузок переменное количество. он и вчитает отгрузки но договор не учитывает, он у него "выпал" из расчетов а теоретически отгрузки должны к нему быть привязаны.


 
Reindeer Moss Eater ©   (2004-07-08 14:52) [27]

потому что "договор ...

Да какая разница почему именно?
Не нужен ему count.

select ...,...,1 from ....

даст то же самое.


 
alexe   (2004-07-08 14:58) [28]

То Johnmen
Кажется узнал :)) Любая попытка использовать конструкцию COUNT(DISTINCT ...) приводит к ошибке (надо было сразу не умничать и попробовать в простом запросе :)).

To Reindeer Moss Eater
Контсрукция select distinct(продукт,клиент,договор), если я правильно понял мысль, даст лишь список:
продукт1/клиент1/договор1
продукт1/клиент1/договор2
...
продукт1/клиент1/договорN
А мне нужно одну строку:продукт1/клиент1/всего договоров1,2,...,N


 
Reindeer Moss Eater ©   (2004-07-08 15:10) [29]

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

Твоя проблема не имеет отношения ни к БД ни к SQL
Определись сначала что ты хочешь посчитать в терминах реального мира, предметной области. А уж потом надо писать запрос


 
Sandman25 ©   (2004-07-08 15:13) [30]

В [18] и [28] написаны противоречащие друг другу предложения.


 
alexe   (2004-07-08 15:27) [31]

ТО Reindeer Moss Eater & Sandman25
Попробую объяснить понятнее.
Допустим, есть клиент1, который взял продукт1 2 раза по договору1, 3 раза по договору2 и 1 раз по договору3. Нужно определить, по скольким договорам осуществлялась отгрузка. В данном случае по трем (именно не общее количество огрузок - 6, не количество отгрузок по договорам - 2,3 и 1 соответственно, а количество договоров для данного клиента по данному продукту - 3).
В общем, все больше укрепляюсь в мнении, что без промежуточной таблицы не обойтись.


 
Sandman25 ©   (2004-07-08 15:30) [32]

[31] alexe   (08.07.04 15:27)

Если Count(distinct contractname) не поддерживается, то действительно одним запросом не обойтись.



Страницы: 1 вся ветка

Текущий архив: 2004.08.01;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.041 c
14-1089830378
GeX
2004-07-14 22:39
2004.08.01
DLL with ASM + Delphi


4-1087048261
Игорь
2004-06-12 17:51
2004.08.01
Перехват открытия файлов


14-1089778433
Dmitriy O.
2004-07-14 08:13
2004.08.01
Что лутше IBdataSet или IBQuery+IBupdateSQL ?


4-1087728431
korvin
2004-06-20 14:47
2004.08.01
"Выгрузить" программу, тормознуть процесс ...


1-1089919209
Vovan
2004-07-15 23:20
2004.08.01
RichTextBox