Текущий архив: 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.52 MB
Время: 0.05 c