Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2004.08.01;
Скачать: [xml.tar.bz2];

Вниз

Как исключить лишние записи из 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.036 c
1-1089868033
cyborg
2004-07-15 09:07
2004.08.01
Проверка имени файла на недопустимые символы


11-1077998244
hermit
2004-02-28 22:57
2004.08.01
Вопрос по KOL Memo


1-1090045555
ko
2004-07-17 10:25
2004.08.01
Процедуры


14-1089651784
pasha_golub (another place)
2004-07-12 21:03
2004.08.01
Будьте бдительны


1-1090243039
Natalie_Q
2004-07-19 17:17
2004.08.01
Из Delphi в HTML





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский