powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Сравнить два списка
16 сообщений из 16, страница 1 из 1
Сравнить два списка
    #38864771
Kirill Razuvaev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте!
Есть простая табличка:
Код: sql
1.
2.
3.
create table MyTable(
KeyID integer,
DataID integer);

с первичным ключом по обоим полям.
И есть, к примеру, три переменные Data1, Data2, Data3 того же типа integer. В переменных могут быть либо значения, либо null. Для каждого КeyID в таблице может быть от 0 до 3 значений.
Вопрос: нужно определить, существует ли для определенного KeyID в таблице значения, записанные в переменных, или нет. Т.е. идентичны ли списки значений в переменных и в таблице. Есть ли элегантный способ определить?
...
Рейтинг: 0 / 0
Сравнить два списка
    #38864779
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kirill Razuvaevтри переменные Data1, Data2, Data3
где?
...
Рейтинг: 0 / 0
Сравнить два списка
    #38864786
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kirill RazuvaevЕсть ли элегантный способ определить?
IN, COUNT(), результат сравнить с тройкой.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Сравнить два списка
    #38864814
Шавлюк Евгений
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kirill Razuvaev,

Первое что приходит в голову сделать процедуру для сравнения select list(DataID) c (Data1, Data2, Data3)
...
Рейтинг: 0 / 0
Сравнить два списка
    #38864852
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kirill RazuvaevДля каждого КeyID в таблице может быть от 0 до 3 значений <...>
нужно определить, существует ли для определенного KeyID в таблице значения, записанные в переменных, или нет. Т.е. идентичны ли списки значений в переменных и в таблице. Есть ли элегантный способ определить?А что делать, если:
1) для keyId = 5 в таблице будут вот такие две записи:
Код: plaintext
1.
2.
5 12 
5 18
2) а переменных задано три : data1 = 18, data2 = 11, data3 = 12 (т.е. список переменных покрывает набор в таблице, но еще и довесок содержит в виде "11")
- ?
Короче, пример с данными не помешал бы...
...
Рейтинг: 0 / 0
Сравнить два списка
    #38864887
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kirill RazuvaevЕсть ли элегантный способ определить?Смотря что ты считаешь элегантным. Про Count и List уже подсказали,
я бы ещё EB добавил (если задача регулярная - лучше даже ХП).
...
Рейтинг: 0 / 0
Сравнить два списка
    #38864889
Шавлюк Евгений
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kirill Razuvaev,

Если можно гарантировать что
1.
Код: sql
1.
select list(t.dataid,'~') from mytable

всегда вернет отсортированный набор;
Тут как понимаю гарантии нет?

2. data1 < data2 < data3 (null может быть в любом месте)
Это гораздо проще обеспечить.

То работает такой запрос:
Код: sql
1.
2.
3.
select 'OK' from rdb$database
left join mytable t on t.keyid = :keyid
having '~'||list(t.dataid,'~')||'~' is not distinct from nullif(coalesce('~'||cast(:data1 as int), '')||coalesce('~'||cast(:data2 as int), '')||coalesce('~'||cast(:data3 as int), ''), '')||'~'
...
Рейтинг: 0 / 0
Сравнить два списка
    #38864899
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шавлюк ЕвгенийЕсли можно гарантировать что list
всегда вернет отсортированный набор;
Тут как понимаю гарантии нет?
Так это не у него гарантии нет, это ни у кого гарантии нет.
Дистинкт разве что добавить по старинке, но это опять же
та ещё гарантия...

В общем, вы ему щас нарекуомендуете таких вот элегантных
запросов типа приведённого вместо нормальной ХП - он-то
выберет какой-нибудь, а потом жалеть будет.

Кирилл, не слушай никого, пиши ХП.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Сравнить два списка
    #38865108
stelvic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хм, а kdv правильный вопрос задал.
...
Рейтинг: 0 / 0
Сравнить два списка
    #38865167
Kirill Razuvaev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdvKirill Razuvaevтри переменные Data1, Data2, Data3
где?Дело происходит в ХП, занимающейся импортом из внешней, не нормализованной таблицы, в которой Data1, Data2, Data3 для каждого KeyID лежат в соседних столбцах.
Задача состоит из двух частей:
1. Определить идентичность (или НЕ идентичность) списков значений, как по количеству, так и по содержимому значений.
2. Синхронизировать списки.

Пока решил так:
Код: 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.
create or alter procedure INT_INV_SYNC_OMVZ (
    INV_REQ_ID D_INTEGER,
    OMVZ1 D_MVZ,
    OMVZ2 D_MVZ,
    OMVZ3 D_MVZ,
    CHECK_ONLY D_BOOLEAN)
returns (
    IS_EQUAL D_BOOLEAN,
    IS_NON_EQUAL D_BOOLEAN)
as
declare variable CNT D_INTEGER;
declare variable CNT1 D_INTEGER;
begin
  IS_EQUAL=1; CNT=0;
  if (OMVZ1 is not null) then begin
    cnt=cnt+1;
    if (not exists(select * from inv_req_omvz where inv_req_id=:INV_REQ_ID and mvz=:OMVZ1)) then IS_EQUAL=0;
  end
  if (OMVZ2 is not null) then begin
    cnt=cnt+1;
    if (not exists(select * from inv_req_omvz where inv_req_id=:INV_REQ_ID and mvz=:OMVZ2)) then IS_EQUAL=0;
  end
  if (OMVZ3 is not null) then begin
    cnt=cnt+1;
    if (not exists(select * from inv_req_omvz where inv_req_id=:INV_REQ_ID and mvz=:OMVZ3)) then IS_EQUAL=0;
  end
  select count(*) from inv_req_omvz where inv_req_id=:INV_REQ_ID into :cnt1;
  if (cnt1<>cnt) then IS_EQUAL=0;
if ((CHECK_ONLY=0)and(IS_EQUAL=0)) then begin
    if (omvz1 is not null) then begin
      if (not exists(select * from inv_req_omvz where inv_req_id=:inv_req_id and mvz=:omvz1)) then
        insert into inv_req_omvz(inv_req_id, mvz) values(:INV_REQ_ID, :OMVZ1);
    end
    if (omvz2 is not null) then begin
      if (not exists(select * from inv_req_omvz where inv_req_id=:inv_req_id and mvz=:omvz2)) then
        insert into inv_req_omvz(inv_req_id, mvz) values(:INV_REQ_ID, :OMVZ2);
    end
    if (omvz2 is not null) then begin
      if (not exists(select * from inv_req_omvz where inv_req_id=:inv_req_id and mvz=:omvz3)) then
        insert into inv_req_omvz(inv_req_id, mvz) values(:INV_REQ_ID, :OMVZ3);
    end
    delete from inv_req_omvz where INV_REQ_ID=:INV_REQ_ID and (not (mvz in (coalesce(:OMVZ1,'-1'), coalesce(:OMVZ2,'-1'), coalesce(:OMVZ3,'-1'))));
  end
  IS_NON_EQUAL=1-IS_EQUAL;
  suspend;
end^

но визуально не очень нравится :-)
...
Рейтинг: 0 / 0
Сравнить два списка
    #38865174
Kirill Razuvaev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шавлюк Евгений2. data1 < data2 < data3 (null может быть в любом месте)
Это гораздо проще обеспечить.Увы, данные внешние, закладываться на их сортировку еще боле опасно, чем на особенности LIST :-) Ну, а сортировать значения в локальных переменных моветоном попахивает :-)
...
Рейтинг: 0 / 0
Сравнить два списка
    #38865493
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kirill Razuvaevвизуально не очень нравится :-)Мне тоже :-)
Код: plaintext
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.
alter sequence g restart with 0;
recreate table inv( id int primary key, req_id int, mvz int, unique(req_id, mvz) using index inv_req_mvz_unq );
commit;
insert into inv values( gen_id(g,1), 2, 200);
insert into inv values( gen_id(g,1), 2, 203);
insert into inv values( gen_id(g,1), 2, 201);

insert into inv values( gen_id(g,1), 1, 103);
insert into inv values( gen_id(g,1), 1, 101);

insert into inv values( gen_id(g,1), 3, 303);
insert into inv values( gen_id(g,1), 3, null);
insert into inv values( gen_id(g,1), 3, 301);

insert into inv values( gen_id(g,1), 4, 400);
insert into inv values( gen_id(g,1), 4, 403);
insert into inv values( gen_id(g,1), 4, 401);
insert into inv values( gen_id(g,1), 4, 404);
commit;


set term ^;
create or alter procedure check_identical(
  a_req_id int,
  a_mvz1 int,
  a_mvz2 int,
  a_mvz3 int
)
returns(is_identical smallint)
as
begin
    for
        with recursive
        inp as (
            --select 2 as a_req_id, 200 as a_mvz1, 201 as a_mvz2, 203 as a_mvz3
            --select 1 as a_req_id, 100 as a_mvz1, 101 as a_mvz2, 103 as a_mvz3
            --select 3 as a_req_id, null as a_mvz1, 301 as a_mvz2, 303 as a_mvz3
            --select 4 as a_req_id, 401 as a_mvz1, 402 as a_mvz2, 404 as a_mvz3
            select :a_req_id as a_req_id, :a_mvz1 as a_mvz1, :a_mvz2 as a_mvz2, :a_mvz3 as a_mvz3
            from rdb$database
        )
        ,n as (select 1 k from rdb$database union all select u.k+1 from n u where u.k<3)
        ,u as(
            select i.a_req_id as rq, decode(n.k, 1, i.a_mvz1, 2, i.a_mvz2, 3, i.a_mvz3) mv
            from inp i, n
        )
        ,d as (
            select rq, mv from u
            union all
            select v.req_id, v.mvz from inv v join inp i on v.req_id = i.a_req_id
        )
        --select * from d
        ,e as(
            select d.rq,d.mv,count(*) c
            from d
            group by d.rq,d.mv
            having count(*)<>2
            rows 1
        )
        select iif( exists(select * from e), 0, 1 ) as is_identical
        from rdb$database
        into is_identical
    do suspend;
end
^ set term ;^
commit;
Test:
Код: plaintext
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.
SQL> select * from inv;

          ID       REQ_ID          MVZ
============ ============ ============
           1            2          200
           2            2          203
           3            2          201
           4            1          103
           5            1          101
           6            3          303
           7            3       <null>
           8            3          301
           9            4          400
          10            4          403
          11            4          401
          12            4          404

SQL> select * from check_identical(2, 200, 201, 203);

IS_IDENTICAL
============
           1

SQL> select * from check_identical(2, 200, null , 203);

IS_IDENTICAL
============
           0

SQL> select * from check_identical(1, 101, 103, null);

IS_IDENTICAL
============
           0

SQL> select * from check_identical(3, null, 303, 301);

IS_IDENTICAL
============
           1

SQL> select * from check_identical(4, 400, 403, 401);

IS_IDENTICAL
============
           0
...
Рейтинг: 0 / 0
Сравнить два списка
    #38865509
Шавлюк Евгений
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоид
Код: plaintext
1.
2.
insert into inv values( gen_id(g,1), 3, 303);
insert into inv values( gen_id(g,1), 3, null);
insert into inv values( gen_id(g,1), 3, 301);

Не правильно, по условию:
Kirill Razuvaevс первичным ключом по обоим полям.
...
Рейтинг: 0 / 0
Сравнить два списка
    #38865532
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шавлюк ЕвгенийТаблоид
Код: plaintext
1.
2.
insert into inv values( gen_id(g,1), 3, 303);
insert into inv values( gen_id(g,1), 3, null);
insert into inv values( gen_id(g,1), 3, 301);

Не правильно, по условию:
Kirill Razuvaevс первичным ключом по обоим полям.Подкрутит, напильник там точно есть.
...
Рейтинг: 0 / 0
Сравнить два списка
    #38865646
Kirill Razuvaev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТаблоидПодкрутит, напильник там точно есть.
Суровое решение :-) Для начала придется разобраться с with recursive, которые я ранее стороной обходил :-)
...
Рейтинг: 0 / 0
Сравнить два списка
    #38865657
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kirill RazuvaevТаблоидПодкрутит, напильник там точно есть.
Суровое решение :-) Для начала придется разобраться с with recursive, которые я ранее стороной обходил :-)recursive здесь только для экономии места. Если в лом с ним разбираться, то вот это:

Код: plaintext
,n as (select 1 k from rdb$database union all select u.k+1 from n u where u.k<3)

-- замени на

Код: plaintext
1.
2.
3.
4.
,n as( 
select 1 k from rdb$database union all 
select 2 k from rdb$database union all 
select 3 k from rdb$database 
)

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


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