powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / условие IN для двух полей?
9 сообщений из 9, страница 1 из 1
условие IN для двух полей?
    #40061338
Anton_1234
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имеется две таблицы: TABLE_1 - таблица имен и TABLE_2 - таблица с данными
нужно для NAME_1 (т.е., в данном примере, для ID=1, 2, 3) вытащить FLOAT_VALUE,
про которые известно, что их ROW_NUM на 2 больше, чем ROW_NUM у TXT_VALUE='q',
в TABLE_2 выделены красным

TABLE_1
ID NAME1 NAME_12 NAME_13 NAME_14 NAME_2

TABLE_2
ID ROW_NUM TXT_VALUE FLOAT_VALUE1 1 q 1 2 w 1 3 11 4 r 1 5 1 6 9.52 1 f 2 2 w 3.52 3 e 2 4 q 2 6 2.13 1 q 3 2 w 3 3 e 2.33 4 r 3 5 3 6 3.64 1 4 2 4.14 3 q 4 4 4 5 3.24 6 y


выполняю селект
Код: plsql
1.
2.
3.
4.
5.
6.
7.
select 
      ID * 100000000 + (ROW_NUM +2) as KLUCH_SOST -- составной ключ,  "+2" потому что нужен ROW_NUM на 2 больше
from 
     TABLE_2
where 
     ID in (select ID from TABLE_1 where NAME='NAME_1')
 and TXT_VALUE='q'



и получаю набор составных ключей, в которых содержится информация как о нужном ID (выделен красным), так и о нужном ROW_NUM
KLUCH_SOST100000003200000006300000003

после чего могу взять нужные значения
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
select 
     FLOAT_VALUE
from 
     TABLE_2
where 
     ID * 100000000 + (ROW_NUM) in
     (
      select 
            ID * 100000000 + (ROW_NUM +2) as KLUCH_SOST -- составной ключ,  "+2" потому что нужен ROW_NUM на 2 больше
     from 
          TABLE_2
      where 
           ID in (select ID from TABLE_1 where NAME='NAME_1')
      and TXT_VALUE='q'
      )



FLOAT_VALUE12.12.3

вроде получил что нужно, но что-то не нравится в этом способе
хотелось бы что-то типа
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
select 
     FLOAT_VALUE
from 
     TABLE_2
where 
     (ID, ROW_NUM) in -- IN для двух полей
     (
      select 
            ID, ROW_NUM +2 as ROW_NUM 
     from 
          TABLE_2
      where 
           ID in (select ID from TABLE_1 where NAME='NAME_1')
      and TXT_VALUE='q'
      )
...
Рейтинг: 0 / 0
условие IN для двух полей?
    #40061340
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anton_1234Имеется две таблицы: TABLE_1 - таблица имен и TABLE_2 - таблица с данными
нужно для NAME_1 (т.е., в данном примере, для ID=1, 2, 3) вытащить FLOAT_VALUE,
про которые известно, что их ROW_NUM на 2 больше, чем ROW_NUM у TXT_VALUE='q'

Код: sql
1.
2.
3.
select t1.float_value from table_2 t1 join table_2 t2 on t1.id=t2.id and t1.row_num=t2.row_num+2
join table_1 on table_1.id=t2.id
where table_1.name='NAME_1' and t2.txt_value='q'
...
Рейтинг: 0 / 0
условие IN для двух полей?
    #40061346
Anton_1234
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov,
Спасибо,
а то я чего-то нагородил, что мне самому не понравилось
...
Рейтинг: 0 / 0
условие IN для двух полей?
    #40061349
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

Зачем рыть TABLE_1 дважды?

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
WITH T AS (
           SELECT  CASE
                     WHEN TXT_VALUE = 'q' THEN LEAD(ROW_NUM,2) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                   END ROW_NUM,
                   CASE
                     WHEN TXT_VALUE = 'q' THEN LEAD(FLOAT_VALUE,2) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                   END FLOAT_VALUE
             FROM  TABLE_2
             WHERE ID IN (
                          SELECT  ID
                            FROM  TABLE_1
                            WHERE NAME = 'NAME_1'
                         )
          )
SELECT  FLOAT_VALUE
  FROM  T
  WHERE ROW_NUM IS NOT NULL
/


SY.
...
Рейтинг: 0 / 0
условие IN для двух полей?
    #40061350
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY

Зачем рыть TABLE_1 дважды?


Упс, не заметил ROW_NUM не сквозной.

SY.
...
Рейтинг: 0 / 0
условие IN для двух полей?
    #40061353
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если шаг небольшой и не меняется/не параметр:

Код: plsql
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.
WITH T AS (
           SELECT  CASE
                     WHEN TXT_VALUE = 'q' THEN
                                            CASE ROW_NUM +2
                                              WHEN LEAD(ROW_NUM) OVER(PARTITION BY ID ORDER BY ROW_NUM) THEN 1
                                              WHEN LEAD(ROW_NUM,2) OVER(PARTITION BY ID ORDER BY ROW_NUM) THEN 1
                                            END
                   END FLAG,
                   CASE
                     WHEN TXT_VALUE = 'q' THEN
                                            CASE ROW_NUM +2
                                              WHEN LEAD(ROW_NUM) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                                                THEN LEAD(FLOAT_VALUE) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                                              WHEN LEAD(ROW_NUM,2) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                                                THEN LEAD(FLOAT_VALUE,2) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                                              -- Добавить еще WHEN если шаг > 2
                                            END
                   END FLOAT_VALUE
             FROM  TABLE_2
             WHERE ID IN (
                          SELECT  ID
                            FROM  TABLE_1
                            WHERE NAME = 'NAME_1'
                         )
          )
SELECT  FLOAT_VALUE
  FROM  T
  WHERE FLAG IS NOT NULL
/



SY.
...
Рейтинг: 0 / 0
условие IN для двух полей?
    #40062200
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY,

Всё тривиальнее и без призяке к длине шага.

Аналитика + группировка (можно обойтись и "where row_num = q_num + 2" если значение всегда есть)
Код: plsql
1.
2.
3.
4.
5.
select id, max(decode(row_num, q_num + 2, float_value)) result
  from (select t.*,
               max(decode(txt_value, 'q', row_num)) over(partition by id) q_num
          from table_2 t)
 group by id


Просто аналитика
Код: plsql
1.
2.
3.
4.
5.
select id, result
  from (select t.*,
               max(float_value) over(partition by id order by row_num range between 2 following and 2 following) result
          from table_2 t)
 where txt_value = 'q'
...
Рейтинг: 0 / 0
условие IN для двух полей?
    #40062230
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кобанчег


Всё тривиальнее и без призяке к длине шага.


"Аналитика + группировка" - а кто сказал что 'q' один на id?

Код: plsql
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.
with table_2 as (
                 select 1 id,1 row_num,'q' txt_value,null float_value from dual union all
                 select 1,3,'q',2 from dual union all
                 select 1,5,'w',1 from dual
                ),
T AS (
           SELECT  CASE
                     WHEN TXT_VALUE = 'q' THEN
                                            CASE ROW_NUM +2
                                              WHEN LEAD(ROW_NUM) OVER(PARTITION BY ID ORDER BY ROW_NUM) THEN 1
                                              WHEN LEAD(ROW_NUM,2) OVER(PARTITION BY ID ORDER BY ROW_NUM) THEN 1
                                            END
                   END FLAG,
                   CASE
                     WHEN TXT_VALUE = 'q' THEN
                                            CASE ROW_NUM +2
                                              WHEN LEAD(ROW_NUM) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                                                THEN LEAD(FLOAT_VALUE) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                                              WHEN LEAD(ROW_NUM,2) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                                                THEN LEAD(FLOAT_VALUE,2) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                                            END
                   END FLOAT_VALUE
             FROM  TABLE_2
          )
SELECT  FLOAT_VALUE
  FROM  T
  WHERE FLAG IS NOT NULL
/

FLOAT_VALUE
-----------
          2
          1

with table_2 as (
                 select 1 id,1 row_num,'q' txt_value,null float_value from dual union all
                 select 1,3,'q',2 from dual union all
                 select 1,5,'w',1 from dual
                )
select id, max(decode(row_num, q_num + 2, float_value)) result
  from (select t.*,
               max(decode(txt_value, 'q', row_num)) over(partition by id) q_num
          from table_2 t)
 group by id
/

        ID     RESULT
---------- ----------
         1          1

SQL>



"Просто аналитика" - да, правда выдаст 'q' для которой нет строки c row_num = row_num('q') + 2:

Код: plsql
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.
with table_2 as (
                 select 1 id,1 row_num,'q' txt_value,null float_value from dual
                ),
T AS (
           SELECT  CASE
                     WHEN TXT_VALUE = 'q' THEN
                                            CASE ROW_NUM +2
                                              WHEN LEAD(ROW_NUM) OVER(PARTITION BY ID ORDER BY ROW_NUM) THEN 1
                                              WHEN LEAD(ROW_NUM,2) OVER(PARTITION BY ID ORDER BY ROW_NUM) THEN 1
                                            END
                   END FLAG,
                   CASE
                     WHEN TXT_VALUE = 'q' THEN
                                            CASE ROW_NUM +2
                                              WHEN LEAD(ROW_NUM) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                                                THEN LEAD(FLOAT_VALUE) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                                              WHEN LEAD(ROW_NUM,2) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                                                THEN LEAD(FLOAT_VALUE,2) OVER(PARTITION BY ID ORDER BY ROW_NUM)
                                            END
                   END FLOAT_VALUE
             FROM  TABLE_2
          )
SELECT  FLOAT_VALUE
  FROM  T
  WHERE FLAG IS NOT NULL
/

no rows selected

with table_2 as (
                 select 1 id,1 row_num,'q' txt_value,null float_value from dual
                )
select id, result
  from (select t.*,
               max(float_value) over(partition by id order by row_num range between 2 following and 2 following) result
          from table_2 t)
 where txt_value = 'q'
/

        ID R
---------- -
         1

SQL>




Но это поправимо:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
with table_2 as (
                 select 1 id,1 row_num,'q' txt_value,null float_value from dual
                )
select id, result
  from (select t.*,
               max(float_value) over(partition by id order by row_num range between 2 following and 2 following) result,
               max(row_num) over(partition by id order by row_num range between 2 following and 2 following) result_row_num
          from table_2 t)
 where txt_value = 'q'
   and result_row_num is not null
/

no rows selected

SQL>



SY.
...
Рейтинг: 0 / 0
условие IN для двух полей?
    #40062467
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY
Но это поправимо
Оба варианта допиливаются для любого числа TXT_VALUE и FLOAT_VALUE, но предпочитаю не усложнять без надобности.

just for fun
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
select *
from TABLE_2
model
return updated rows
partition by (id)
dimension by (row_num, txt_value)
measures (float_value, row_num q_num)
rules
(
  q_num[any, 'q'] = cv(row_num),
  float_value[any, 'q'] = max(float_value)[q_num[cv(row_num), 'q'] + 2, any]
)


+
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
select *
from TABLE_2
match_recognize
(
  partition by id
  order by row_num
  measures x.float_value m
  pattern (strt x*)
  define
    strt as strt.txt_value = 'q',
    x as x.row_num <= strt.row_num + 2
)


Только вот не надо говорить, а если q, q идут подряд. (тогда явно указывается after match кляуза)

А вообще любая однопроходность может оказаться бссмысленной если у ТС 100500 строк на каждый ID и имеются индексы по TXT_VALUE и ROW_NUM.
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / условие IN для двух полей?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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