Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > Запрос с группировкой и подсчетом сумм


Автор: begin 12.3.2009, 01:14
Есть таблица товаров:
Код

id_tovar
code
id_office
status


Нужно выбрать все id_tovar где status<3, но при этом нужно сгруппировать товары с одинаковым полем code, и подсчитать сколько их есть в каждом из филиалов (обозначены id_office).
Работаю с MySQL через BDE.

Подскажите, как можно составить такой запрос? Ничего на ум не приходит, кроме каких-то промежуточных запросов и временных массивов.

Автор: Akella 12.3.2009, 02:35
может меня кто поправит?
Код

select id_tovar, code, count(id_office) from table
group by 1, 2, 3
where status < 3

Автор: Данкинг 12.3.2009, 02:39
Akella, а по вычисляемому полю (т.е. count) разве будет работать group ?

Автор: Akella 12.3.2009, 02:54
значит
Код

select id_tovar, code, count(id_office) from table
group by 1, 2
where status < 3

Автор: Frees 12.3.2009, 07:22
Akella, в твоем примере count всегда 1 будет возвращать, т.к группировать ничего не будет потому что выбран id_tovar

Автор: Akella 12.3.2009, 13:13
и вообще group by  должен идти последним  smile  smile , да, вот я стормозил smile 

Автор: Frees 12.3.2009, 13:24
Цитата(begin @  12.3.2009,  03:14 Найти цитируемый пост)
Нужно выбрать все id_tovar где status<3, но при этом нужно сгруппировать товары с одинаковым полем code, и подсчитать сколько их есть в каждом из филиалов (обозначены id_office).

1 запросом этого не сделать!либо выбирать id_tovar либо группировать, одновременно нельзя

Автор: Akella 12.3.2009, 13:44
Код

select id_tov, code, count(id_office) from NEW_TABLE
where status < 3
group by 2, 1

Автор: Kbl4AH 12.3.2009, 16:33
Код

select id_office, count(id_tovar) from table
where id_tovar in (select id_tovar from table where status < 3 group by code)
group by id_office

ЗЫ. begin, ты, по-моему, сам не понял что спросил...
Приводи кусок таблицы и нужный результат и запрос тебе будет обеспечен! smile 

Автор: begin 12.3.2009, 22:36
Уточню: мне нужно подсчитать количество разных code в каждой из id_office.
Если в таблице будут такие данные:
Код

code   id_office
005    1
006    2
002    2
002    3
004    1
004    1
004    1
004    3
002    2
006    1

то запрос должен выдать такую таблицу:
Код

code id_office=1 id_office=2 id_office=3 id_office=4 id_office=5 id_office=6
002            0                2                1               0                   0               0
004            3                0                1               0                   0               0
005            1                0                0               0                   0               0
006            1                1                0               0                   0               0

Автор: Kbl4AH 12.3.2009, 23:29
Цитата(begin @  12.3.2009,  01:14 Найти цитируемый пост)
Нужно выбрать все id_tovar где status<3, но при этом нужно сгруппировать товары с одинаковым полем code, и подсчитать сколько их есть в каждом из филиалов (обозначены id_office).

Цитата(begin @  12.3.2009,  22:36 Найти цитируемый пост)
Уточню: мне нужно подсчитать количество разных code в каждой из id_office.

совершенно разные вещи...

Добавлено через 3 минуты и 30 секунд
Код

select code, decode(id_office, 1, count(id_office)), ...,  decode(id_office, N, count(id_office)) from table group by code

Автор: Kbl4AH 13.3.2009, 00:09
Нда, с запросом немного приврал (без компа делал)...
Вот работающий:http://ipicture.ru/

Автор: begin 13.3.2009, 00:10
Цитата(Kbl4AH @ 12.3.2009,  23:29)
Код

select code, decode(id_office, 1, count(id_office)), ...,  decode(id_office, N, count(id_office)) from table group by code

А после выполнения запроса из каких переменных брать количество каждого кода в каждом из филиалов? А то я что то запутался в вашем примере..

Автор: begin 13.3.2009, 00:35
Но это же BDE - там ведь нельзя использовать вложенные запросы. Разве нет?  smile 

Автор: Kbl4AH 13.3.2009, 00:39
Цитата(begin @  13.3.2009,  00:35 Найти цитируемый пост)
Но это же BDE - там ведь нельзя использовать вложенные запросы. Разве нет?

не знаю.... но мне кажется можно... для MySQL вместо decode - if

Автор: Frees 13.3.2009, 07:14
Цитата(begin @  13.3.2009,  02:35 Найти цитируемый пост)
Но это же BDE - там ведь нельзя использовать вложенные запросы. Разве нет?  smile 

vj;tyj ИВУ пофик что за запрос его же MySQL выполняет 

Автор: begin 13.3.2009, 13:22
Цитата(Kbl4AH @ 13.3.2009,  00:09)
Нда, с запросом немного приврал (без компа делал)...
Вот работающий:http://ipicture.ru/

порылся - в MySQL действительно нужно использовать If вместо Decode. С учетом этого запрос будет выглядеть так:

Код

select code, sum(of1), sum(of2), sum(of3) 
from (select code, if(id_ffice,1,count(code),0) of1, if(id_ffice,2,count(code),0) of2, if(id_ffice,3,count(code),0) of3 
from table group by code,id_ofice) 
group by code


Что такое of1..of3? Это какие то временные переменные для промеждуточного хранения количества найденных полей?

Как мне получить доступ к суммам? Ведь, например, к полю code я получаю доступ так:
Код

i:=query1.Fields.Fields[1].AsInteger;

Автор: Kbl4AH 13.3.2009, 15:50
Цитата(begin @  13.3.2009,  13:22 Найти цитируемый пост)
Что такое of1..of3? Это какие то временные переменные для промеждуточного хранения количества найденных полей?

это алиасы полей... поле будет называться так как ты его в вопросе выбираешь, например, if(id_ffice,1,count(code),0), но это неудобно и для него пишут алиас (типа псевдоним в удобной форме)... для алиас исользуется слово as, т.е 
Код

select pole1 as p1, pole2 as p2 from t
 просто я as опускаю... еще без них не обойтись в запросах типа 
Код

select sum(a) from (select sum(a) from t)

будет ошибка, т.к. вложенный запрос возвращает поле с именем sum(a), а вышесто\щий запрос воспринимает его не как название поля, а как операцию суммирования над полем а (которое даже подзапросом и не возвращается)... поэтому надо юзать алиас и делать так 
Код

select suma as sa from (select sum(a) as suma from t)

Цитата(begin @  13.3.2009,  13:22 Найти цитируемый пост)
Как мне получить доступ к суммам? Ведь, например, к полю code я получаю доступ так:

запрос лучше напиши так (добавь алиасы, чтоб не было проблем при модификации запроса; т.е. перед написанием запроса надо решить какие поля он будет возвращать, а реализация может быть разная... в твоем случае возвращает код и какую-то инфу для списка офисов... соответсвенные алиасы и используй)...
Код

select code, sum(of1) of1, sum(of2) of2, sum(of3) of3 
from (select code, if(id_ffice,1,count(code),0) of1, if(id_ffice,2,count(code),0) of2, if(id_ffice,3,count(code),0) of3 
from table group by code,id_ofice) 
group by code

если поле code у тебя 1-е, то поле of1 соответственно будет 2-м...
Код

i:=query1.Fields.Fields[2].AsInteger;

Но обращаться к полю по номеру не рекомендую... лучше обращаться по имени!!!

Автор: Akella 13.3.2009, 17:58
нифигасе вы тут намутили smile 

Автор: begin 14.3.2009, 01:51
сделал как посоветовали, с алиасами, уже готовый для использования запрос:
Код

query1.SQL.Add('select code,name,price,sum(of1),sum(of2),sum(of3) from '
+'(select code, if(id_ffice,1,count(code),0) as of1, if(id_ffice,2,count(code),0)'
+' as of2, if(id_ffice,3,count(code),0) as of3 from t_tovar where data1=:txt group by code,id_ofice) '
+'group by code');
query1.ParamByName('txt').AsDate:=DateTimePicker4.Date;

но при выполнении запроса выдает ошибку:
Код

expression expected, but 'if' found - Native error: 30160.


где же ошибка? чувствую, что неправильно использую конструкцию if в запросе smile 

Автор: Kbl4AH 14.3.2009, 02:21
Цитата(begin @  14.3.2009,  01:51 Найти цитируемый пост)
сделал как посоветовали

тебе посветовали не так, а так
Код

select code, sum(of1) of1, sum(of2) of2, sum(of3) of3 ...

Цитата(begin @  14.3.2009,  01:51 Найти цитируемый пост)
чувствую, что неправильно использую конструкцию if в запросе

неужели?! а в нете позыркать как правильно использовать? ты с MySQL работаешь!!! я с ней не работаю и в глаза не видел...
Цитата

IF(expr1,expr2,expr3) 
Если expr1 равно значению ИСТИНА (expr1 <> 0 и expr1 <> NULL), то функция IF() возвращает expr2, в противном случае - expr3. В зависимости от контекста функция IF() может возвращать либо числовое, либо строковое значение: 
mysql> SELECT IF(1>2,2,3);
        -> 3
mysql> SELECT IF(1<2,'yes','no');
        -> 'yes'

Автор: begin 14.3.2009, 16:00
Исправил конструкцию if (стояла запятая вместо знака "равно") и добавил алиасы:
Код

query1.SQL.Add('select code,name,price,sum(of1) as of12,sum(of2) as of22,'
+'sum(of3) as of32,sum(of4) as of42,sum(of5) as of52,sum(of6) as of62'
+' from (select code, if(id_office=1,count(code),0) as of1, if(id_office=2,count(code),0)'
+' as of2, if(id_office=3,count(code),0) as of3, if(id_office=4,count(code),0) as of4'
+', if(id_office=5,count(code),0) as of5, if(id_office=6,count(code),0) as of6'
+' from t_tovar where data1=:txt group by code,id_ofice) group by code');
query1.ParamByName('txt').AsDate:=DateTimePicker4.Date;
query1.Open;


и все равно выдает ту же ошибку  smile 

Автор: Kbl4AH 14.3.2009, 17:35
Цитата(begin @  14.3.2009,  16:00 Найти цитируемый пост)
и все равно выдает ту же ошибку

ну, я уже не знаю, чем тебе помочь... потому что запрос - работающий!!!
1) перед добавлением запроса в Query ты очищаешь предыдущий ....SQL.Clear?
2) проверь запрос на работоспособность в SQL с константой вмесо праметра txt.
3) 

пля, тока щас заметил... begin, ты хоть немного думаешь? Тебя же спросили, что запрос должен возвращать...
Цитата(begin @  14.3.2009,  16:00 Найти цитируемый пост)
query1.SQL.Add('select code,name,price,sum(of1) as of12,sum(of2) as of22,'+'sum(of3) as of32,sum(of4) as of42,sum(of5) as of52,sum(of6) as of62'+' from (select code, if(id_office=1,count(code),0) as of1, if(id_office=2,count(code),0)'+' as of2, if(id_office=3,count(code),0) as of3, if(id_office=4,count(code),0) as of4'+', if(id_office=5,count(code),0) as of5, if(id_office=6,count(code),0) as of6'+' from t_tovar where data1=:txt group by code,id_ofice) group by code');query1.ParamByName('txt').AsDate:=DateTimePicker4.Date;query1.Open;

вообще-то, подзапрос не возвращает поля name и price... так что нельзя их выбрать из подзапроса!!! smile 

Автор: begin 14.3.2009, 22:13
оказалось, ошибка в самой конструкции if  smile 
Моя MySQL почему то не понимала такую конструкцию. Пришлось сделать так, и все заработало:

Код

squery1.SQL.Add('select code,sum(of0) as of02,sum(of1) as of12,sum(of2) as '
+'of22,sum(of3) as of32,sum(of4) as of42,sum(of5) as of52,sum(of6) as of62 '
+'from (select code,'
+'case when id_office_2=0 then count(code) else 0 end as of0, '
+'case when id_office_2=1 then count(code) else 0 end as of1, '
+'case when id_office_2=2 then count(code) else 0 end as of2, '
+'case when id_office_2=3 then count(code) else 0 end as of3, '
+'case when id_office_2=4 then count(code) else 0 end as of4, '
+'case when id_office_2=5 then count(code) else 0 end as of5, '
+'case when id_office_2=6 then count(code) else 0 end as of6 '
+'from t_tovar where status=1 group by code,id_office_2) group by code order by code asc');


Автор: Zloxa 15.3.2009, 00:22
ребят, чота вы шибка перемудрили
Аггрегат можно считать по выражению
Код

select code
         , count(case when id_office = 1 then 1 end) off1 -- sum(if(id_office = 1,1,0))
         , count(case when id_office = 2 then 1 end) off2
         , count(case when id_office = 3 then 1 end) off3
...
from table 
group by code

Или я чота недопонял?

ЗЫ.
Я вот давно хотел спросить у когото, кто использует конструкцию типа
Код

Query.SQL.clear;
Query.SQL.Add(SQLText);

Почему нельзя просто:
Код

Query.SQL.Text = SQLText;

Автор: former 15.3.2009, 00:34
Цитата(Zloxa @  15.3.2009,  00:22 Найти цитируемый пост)
Я вот давно хотел спросить у когото, кто использует конструкцию типа
Выделить всёкод Pascal/Delphi
1:
2:
    
Query.SQL.clear;
Query.SQL.Add(SQLText);

Почему нельзя просто:
Выделить всёкод Pascal/Delphi
1:
    
Query.SQL.Text = SQLText;



Zloxa, посмотри предыдущие темы там во многих случаях именно так. Это как кому нравится. smile 

Автор: Данкинг 15.3.2009, 00:41
Цитата(Zloxa @  15.3.2009,  00:22 Найти цитируемый пост)
Я вот давно хотел спросить у когото, кто использует конструкцию типа

Дело привычки. Я и так тоже делаю:
Код

Query.SQL.clear;
Query.SQL.Text = SQLText;

 smile 

Автор: Kbl4AH 15.3.2009, 11:02
Zloxa, я раньше делал с Add, т.к. мне так показали, но потом понял, что так неудобно и теперь только Text использую...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)