powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / покритикуйте, дайте совет по алгоритму
6 сообщений из 6, страница 1 из 1
покритикуйте, дайте совет по алгоритму
    #39847496
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
есть две таблицы

Код: plaintext
1.
2.
3.
4.
5.
Pipe_List_20 - с полями House_Pipe_Code и Group_House_Pipe_Code  (максимум 5 000 записей)
                    (House_Pipe_Code уникальное)

Pipe_List_10 - с полями House_Pipe_Code, Account_Pipe_Code и Group_House_Pipe_Code (максимум 200 000)
                    ( один Account_Pipe_Code может быть привязан к нескольким House_Pipe_Code)
надо заполнить поле Group_House_Pipe_Code (от 1 до ....) таким образом чтобы один и тот-же
Account_Pipe_Code не попал в разные Group_House_Pipe_Code
Как то коряво написал но надеюсь что суть понятна
здесь процедура, которая мне не совсем нравится
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
create procedure Rcalc_Set_Group_House_Pipe_Code
as
declare variable House_Pipe_Code         Tcode;
declare variable Group_House_Pipe_Code   Tcode;
declare variable R_Group_House_Pipe_Code Tcode;
begin

  Group_House_Pipe_Code = 0;
  for select House_Pipe_Code
        from Rcalc_Temp_Pipe_List_20
        order by House_Pipe_Code
      into :House_Pipe_Code
  do begin -- По домовым вводам
    -- Проверим а не цепляются ли вводы на лицевые для домового ввода House_Pipe_Code к другим домовым вводам
    R_Group_House_Pipe_Code = null;
    select first 1 R.Group_House_Pipe_Code
      from Rcalc_Temp_Pipe_List_10 L
        join Rcalc_Temp_Pipe_List_10 R on R.Account_Pipe_Code = L.Account_Pipe_Code and
              R.Group_House_Pipe_Code is not null
      where L.House_Pipe_Code = :House_Pipe_Code
        and R.House_Pipe_Code < :House_Pipe_Code
    into :R_Group_House_Pipe_Code;

    if (R_Group_House_Pipe_Code is not null) then
    begin -- Цепляются
      --> Установим существующую группу
      update Rcalc_Temp_Pipe_List_20
        set Group_House_Pipe_Code = :R_Group_House_Pipe_Code
        where House_Pipe_Code = :House_Pipe_Code;

      update Rcalc_Temp_Pipe_List_10
        set Group_House_Pipe_Code = :R_Group_House_Pipe_Code
        where House_Pipe_Code = :House_Pipe_Code;
    end -- Цепляются
    else begin -- Не цепляются
      --> Установим новую группу
      Group_House_Pipe_Code = Group_House_Pipe_Code + 1;
      update Rcalc_Temp_Pipe_List_20
        set Group_House_Pipe_Code = :Group_House_Pipe_Code
        where House_Pipe_Code = :House_Pipe_Code;

      update Rcalc_Temp_Pipe_List_10
        set Group_House_Pipe_Code = :Group_House_Pipe_Code
        where House_Pipe_Code = :House_Pipe_Code;
    end -- Не цепляются
  end -- По домовым вводам
end


кажется что можно проще и элегантней все сделать
однако голова уже не варит :(
...
Рейтинг: 0 / 0
покритикуйте, дайте совет по алгоритму
    #39847514
KreatorXXI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

да, действительно, ничего не понятно. А какая связь между таблицами? Поля таблиц одинаковые. Вы бы привели DDL. И ещё хорошо бы увидеть результат, который Вы хотите увидеть. Не тысячи записей, а хотя бы несколько.
...
Рейтинг: 0 / 0
покритикуйте, дайте совет по алгоритму
    #39847521
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
    -- Проверим а не цепляются ли вводы на лицевые для домового ввода House_Pipe_Code к другим домовым вводам
    R_Group_House_Pipe_Code = null;
    select first 1 R.Group_House_Pipe_Code
      from Rcalc_Temp_Pipe_List_10 L
        join Rcalc_Temp_Pipe_List_10 R on R.Account_Pipe_Code = L.Account_Pipe_Code and
              R.Group_House_Pipe_Code is not null
      where L.House_Pipe_Code = :House_Pipe_Code
        and R.House_Pipe_Code < :House_Pipe_Code
    into :R_Group_House_Pipe_Code;



а если там больше одной записи, остальные просто игнорируем?
...
Рейтинг: 0 / 0
покритикуйте, дайте совет по алгоритму
    #39847535
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KreatorXXIm7m,

да, действительно, ничего не понятно. А какая связь между таблицами? Поля таблиц одинаковые. Вы бы привели DDL. И ещё хорошо бы увидеть результат, который Вы хотите увидеть. Не тысячи записей, а хотя бы несколько.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
    Pipe_List_20.House_Pipe_Code  
               21                                                       
               22                                                       
               23                                                       
               24                                                       

    Pipe_List_10.House_Pipe_Code       Pipe_List_10.Account_Pipe_Code       
                21                                                   7
                21                                                    2
                21                                                    3
                22                                                   4
                22                                                   5
                23                                                    6
                23                                                    1
                23                                                    7
                 24                                                   8
                24                                                    9
                24                                                    10      


Вот такое должны получить ( и соответственно для таблицы Pipe_List_10 тоже самое)
впрочем хватит только для Pipe_List_20
Код: plaintext
1.
2.
3.
4.
5.
    Pipe_List_20.House_Pipe_Code     Group_House_Pipe_Code 
               21                                                       1
               22                                                       2
               23                                                       1
               24                                                       3
...
Рейтинг: 0 / 0
покритикуйте, дайте совет по алгоритму
    #39847540
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисm7m
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
    -- Проверим а не цепляются ли вводы на лицевые для домового ввода House_Pipe_Code к другим домовым вводам
    R_Group_House_Pipe_Code = null;
    select first 1 R.Group_House_Pipe_Code
      from Rcalc_Temp_Pipe_List_10 L
        join Rcalc_Temp_Pipe_List_10 R on R.Account_Pipe_Code = L.Account_Pipe_Code and
              R.Group_House_Pipe_Code is not null
      where L.House_Pipe_Code = :House_Pipe_Code
        and R.House_Pipe_Code < :House_Pipe_Code
    into :R_Group_House_Pipe_Code;




а если там больше одной записи, остальные просто игнорируем?

я чего-то считал что если больше одной (а это практически всегда, за исключением вырожденных случаев) то у них у всех одинаковый R.Group_House_Pipe_Code (ну так должно быть если алгоритм правильный)
однако ты заставил меня задуматься и я понял что ошибся (неправильный алгоритм работы процедуры) :(
...
Рейтинг: 0 / 0
покритикуйте, дайте совет по алгоритму
    #39847579
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

переписал, но все равно не нравится (рекурсия не нравится), да и не уверен ни в правильности алгоритма ни в скорости работы

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
create or alter procedure Rcalc_Group_House_Pipe_Utl (
  A_House_Pipe_Code  Tcode,
  A_Group_House_Pipe Tcode)
as
declare variable House_Pipe_Code Tcode;
begin

  --> Установим  группу
  update Rcalc_Temp_Pipe_List_20
    set Group_House_Pipe = :A_Group_House_Pipe
    where House_Pipe_Code = :A_House_Pipe_Code;

  update Rcalc_Temp_Pipe_List_10
    set Group_House_Pipe = :A_Group_House_Pipe
    where House_Pipe_Code = :A_House_Pipe_Code;

  -- Проверим а не цепляются ли вводы на лицевые для домового ввода A_House_Pipe_Code к другим домовым вводам
  for select distinct R.House_Pipe_Code
        from Rcalc_Temp_Pipe_List_10 L
          join Rcalc_Temp_Pipe_List_10 R on R.Account_Pipe_Code = L.Account_Pipe_Code and
                R.Group_House_Pipe is not null
        where L.House_Pipe_Code = :A_House_Pipe_Code
      into :House_Pipe_Code
  do begin
    -- Установим существующую группу
    execute procedure Rcalc_Group_House_Pipe_Utl(House_Pipe_Code, :A_Group_House_Pipe);
  end
end
-------------
create or alter procedure Rcalc_Group_House_Pipe
as
declare variable House_Pipe_Code   Tcode;
declare variable Group_House_Pipe  Tcode;
declare variable Account_Pipe_Code Tcode;
begin

  Group_House_Pipe = 0;
  for select House_Pipe_Code
        from Rcalc_Temp_Pipe_List_20
        order by House_Pipe_Code
      into :House_Pipe_Code
  do begin -- По домовым вводам
    if (exists(select *
                 from Rcalc_Temp_Pipe_List_20 R20
                 where R20.House_Pipe_Code = :House_Pipe_Code
                   and R20.Group_House_Pipe is null)) then
    begin -- Для этого ввода группу еще не установили
      --> Установим новую группу
      Group_House_Pipe = Group_House_Pipe + 1;
      execute procedure Rcalc_Group_House_Pipe_Utl(House_Pipe_Code, :Group_House_Pipe);
    end -- Для этого ввода группу еще не установили
  end -- По домовым вводам

  -- Проверка правильности работы
  select first 1 R10.Account_Pipe_Code --,count(distinct r10.group_house_pipe)
    from Rcalc_Temp_Pipe_List_10 R10
    group by R10.Account_Pipe_Code
    having count(distinct R10.Group_House_Pipe) > 1
  into :Account_Pipe_Code;

  if (Account_Pipe_Code is not null) then
    exception Esys_Error 'Более одной группы для ввода лицевого =' || cast(Account_Pipe_Code as varchar(16));

  select first 1 R10.Account_Pipe_Code
    from Rcalc_Temp_Pipe_List_10 R10
    where R10.Group_House_Pipe is null
  into :Account_Pipe_Code;
  if (Account_Pipe_Code is not null) then
    exception Esys_Error 'Отсутствует группа для ввода лицевого =' || cast(Account_Pipe_Code as varchar(16));
end




Ну и DDL таблиц, так на всякий
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
CREATE GLOBAL TEMPORARY TABLE RCALC_TEMP_PIPE_LIST_20 (
    CODE                  TCODENN /* TCODENN = INTEGER NOT NULL */,
    HOUSE_PIPE_CODE       TCODE /* TCODE = INTEGER */,
-- Здесь еще несколько полей к делу не относящихся
    GROUP_HOUSE_PIPE      TCODE /* TCODE = INTEGER */
) ON COMMIT PRESERVE ROWS;

ALTER TABLE RCALC_TEMP_PIPE_LIST_20 ADD CONSTRAINT PK_RCALC_TEMP_PIPE_LIST_20 PRIMARY KEY (CODE);
CREATE UNIQUE INDEX RCALC_TEMP_PIPE_LIST_20_IDX1 ON RCALC_TEMP_PIPE_LIST_20 (HOUSE_PIPE_CODE);
--------------------------------------------------------

CREATE GLOBAL TEMPORARY TABLE RCALC_TEMP_PIPE_LIST_10 (
    CODE                  TCODENN  /* TCODENN = INTEGER NOT NULL */,
    HOUSE_PIPE_CODE       TCODE /* TCODE = INTEGER */,
-- Здесь еще несколько полей к делу не относящихся
    ACCOUNT_PIPE_CODE     TCODE /* TCODE = INTEGER */,
    GROUP_HOUSE_PIPE      TCODE /* TCODE = INTEGER */
) ON COMMIT PRESERVE ROWS;


ALTER TABLE RCALC_TEMP_PIPE_LIST_10 ADD CONSTRAINT PK_RCALC_TEMP_PIPE_LIST_10 PRIMARY KEY (CODE);
CREATE INDEX RCALC_TEMP_PIPE_LIST_10_IDX1 ON RCALC_TEMP_PIPE_LIST_10 (HOUSE_PIPE_CODE);
CREATE INDEX RCALC_TEMP_PIPE_LIST_10_IDX2 ON RCALC_TEMP_PIPE_LIST_10 (ACCOUNT_PIPE_CODE);


...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / покритикуйте, дайте совет по алгоритму
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]