Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Группировка записей в НД


JS2 ©   (2009-10-22 11:04:00) 

SELECT'ом формирую НД. Получается, к примеру:

item_id | group_id
------------------
2                16
5                16
6                16
17              16
21              22
22              22
36              7
74              7

P.S. ORDER BY group_id

Нужно сделать следующие: пройти по всему набору группируя в сроку Item_id с
одинаковыми group_id + вывод, т.е. для данного примера должно быть так:

1 - ShowMessage -> 2,5,6,17
2 - ShowMessage -> 21,22
3 - ShowMessage -> 36,74

Как бы это написать алгоритм пограмотнее?


JS2   (2009-10-22 12:03:00) [1]


> если датасет пустой


А если предварительно добавить проверку на пустой датасет имеет ли смысл проверять ItemIds перед Delete(ItemIds, 1, 1) и перед последним ShowMessage.


palva   (2009-10-22 11:54:00) [2]


>    query_ByField.First;
>    GroupID := field_group_id.AsInteger;

Здесь также будут неприятности, если датасет пустой.


palva   (2009-10-22 11:48:00) [3]


> if ItemIds[1] = ',' then
>        Delete(ItemIds, 1, 1);

Вот это непонятно зачем нужно. Тем более, что ItemIds может быть пустой строкой и проверка первого символа может привести к неприятностям.
Перед последним ShowMessage полезно проверить, что строка не пустая. Иначе будет ненужный вывод пустой строки в случае пустого множества записей.


JS2   (2009-10-22 11:32:00) [4]


> palva ©


кажется, я так и делал. Вот код:

procedure Tform_Main.Button1Click(Sender: TObject);
var
 ItemIds: string;
 GroupID: Integer;
 field_group_id, field_item_id: TField;
begin
 with DMConnection do
 begin
   field_group_id := query_ByField.FieldByName('group_id');
   field_item_id := query_ByField.FieldByName('item_id');

   query_ByField.First;
   GroupID := field_group_id.AsInteger;
   ItemIds := '';

   while not query_ByField.Eof do
   begin
     if field_group_id.AsInteger = GroupID then
       ItemIds := ItemIds + ', '
     else
     begin
       ShowMessage(ItemIds);
       ItemIds := '';
     end;
     ItemIds := ItemIds + field_item_id.AsString;
     GroupId := field_group_id.AsInteger;

     if ItemIds[1] = ',' then
       Delete(ItemIds, 1, 1);

     query_ByField.Next;
   end;
   ShowMessage(ItemIds);
 end;
end;


Посмотрите может есть какие-то упущения?


palva   (2009-10-22 11:24:00) [5]

В разных вариантах подобная задача очень часто встречается. Полезно придерживаться некоторого шаблона, чтобы в следующий раз не думать.

Сохраняйте значение group_id в отдельной переменной, и на каждой итерации у вас будет значение group_id на предыдущей итерации.
Если значение group_id на очередной итерации то же самой, что и на предыдущей, то накапливайте item_id в строке для вывода. Если оно другое, то выводите строку в ShowMessage и очищайте ее.
По особому должна быть выполнена самая первая итерация (не выводить ShowMessage), а также следует выполнить дополнительные действия после окончания цикла -  выполнить ShowMessage, если строка вывода не пустая.


Л.Д.   (2009-10-22 11:10:00) [6]


> Так ты же его уже написал


вообщем-то написал, но не совсем удачный, как мне кажется


JS2   (2009-10-22 11:10:00) [7]

Удалено модератором


Sergey13   (2009-10-22 11:08:00) [8]

> [0] JS2   (22.10.09 11:04)
> Как бы это написать алгоритм пограмотнее?

Так ты же его уже написал

> пройти по всему набору группируя в сроку Item_id с одинаковыми group_id + вывод


Наверх

Титульная страница Поиск, карта сайта Написать письмо