Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / select в updete вставить rownum / 24 сообщений из 24, страница 1 из 1
31.01.2018, 08:29
    #39593692
iv_roman_vl
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
Коллеги, добрый день!

У меня есть такой набор данных, например:
Код: plsql
1.
select a from t where id in (25,26,27) order by id asc;



Результат а, например:
3
7
11

Мне нужно сделать update поля "а" по rownum(т.е. значения поля "а" стали по порядку):
1
2
3

Такой вариант не прокатывает:
Код: plsql
1.
update (select rownum, a from t where id in (25,26,27) order by id asc) set a = rownum;



Помогите, плиз!
...
Рейтинг: 0 / 0
31.01.2018, 08:30
    #39593694
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
iv_roman_vlТакой вариант не прокатывает:
Код: plsql
1.
update (select rownum, a from t where id in (25,26,27) order by id asc) set a = rownum;

RTFM MERGE
...
Рейтинг: 0 / 0
31.01.2018, 08:36
    #39593696
Dshedoo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
Код: plsql
1.
2.
3.
4.
5.
6.
MERGE INTO t
USING (select rownum as x, id from t where id in (25,26,27) order by id asc) z
ON (t.id = z.id)
WHEN MATCHED 
THEN UPDATE 
 SET t.a = z.x
...
Рейтинг: 0 / 0
31.01.2018, 08:37
    #39593697
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
iv_roman_vl
Код: plsql
1.
update (select rownum, a from t where id in (25,26,27) order by id asc) set a = rownum;

rownum формируется до сортировки.
Для приведенного случая проще декодить id, чем городить подзапросы.
...
Рейтинг: 0 / 0
31.01.2018, 08:39
    #39593699
Dshedoo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
Dshedoo,

Код: plsql
1.
USING (select row_number() OVER(order by id asc) as x, id from t where id in (25,26,27)) z
...
Рейтинг: 0 / 0
31.01.2018, 08:52
    #39593703
iv_roman_vl
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
Dshedoo,

Спасибо!!! Работает!!!
...
Рейтинг: 0 / 0
31.01.2018, 10:49
    #39593767
iv_roman_vl
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
Всем спасибо за участие!
Применил вышеуказанные способы и все работает!
Но немного не нравится лаконничность решения.

Задача звучит так:
Книги лежат на полках. У каждой книги на полке есть свое место(номер места).
Книги могут перемещать с полки на полку, либо в начало полки либо в конец.
При перемещении книг в начало полки, номер места перемещаемых книг начинается с 1. Номер места уже имеющихся книг на полке начинается с количества добавленных книг на полку. При этом номера книг с полки откуда переместили, пересчитывается с 1.
При перемещении книг в конец полки, номера книг имеющихся на полке остается прежним, а номера книг перемещаемых на полку начинается с количества книг присутствующих на полке. При этом номера книг с полки откуда переместили, пересчитывается с 1.

Например:
Код: sql
1.
2.
3.
4.
5.
6.
7.
IdКниги| НомерПолки | НомерКнигиНаПолке
1              1                    1
2              1                    2
3              1                    3
4              2                    1
5              2                    2
6              2                    3



При перемещении книг 4,5 с полки 2 на полку 1 в начало полки :
Код: sql
1.
2.
3.
4.
5.
6.
7.
IdКниги| НомерПолки | НомерКнигиНаПолке
1              1                    3
2              1                    4
3              1                    5
4              1                    1
5              1                    2
6              2                    1



При перемещении книг 4,5 с полки 2 на полку 1 в конец полки :
Код: sql
1.
2.
3.
4.
5.
6.
7.
IdКниги| НомерПолки | НомерКнигиНаПолке
1              1                    1
2              1                    2
3              1                    3
4              1                    4
5              1                    5
6              2                    1



Я реализовал это так, начну
Код: plsql
1.
с перемещения книг в конец полки

:
Вначале нахожу количество книг на той полке на которую хочу переместить
Код: plsql
1.
select count(id) into count from Книги where Полка = 1;


Затем, перемещаю книги на полку:
Код: plsql
1.
2.
3.
4.
5.
6.
MERGE INTO Книги
USING (select rownum as x, id from Книги where IDКниги in (4,5) order by id asc) z
ON (Книги.IDКниги = z.id)
WHEN MATCHED 
THEN UPDATE 
 SET Книги.НомерКнигиНаПолке = z.x + count, Книги.НомерПолки = 1;


Локаничность тут меня устраивает.

А теперь,
Код: plsql
1.
с перемещения книг в начало полки

:
Перенумеровываю места книг на полке откуда забираем книги:
Код: plsql
1.
2.
3.
4.
5.
6.
MERGE INTO Книги
USING (select rownum as x, id from Книги where Полка = 2 and IDКниги not in (4,5) order by id asc) z
ON (Книги.IDКниги = z.IDКниги)
WHEN MATCHED 
THEN UPDATE 
 SET Книги.НомерКнигиНаПолке = z.x



Далее, нахожу количество перемещаемых книг:
Код: plsql
1.
select count(id) into count from Книги where id in (4,5);



Далее, Перенумеровываю места книг на полке на которую хочу поставить книги начиная с количества перемещаемых книг:
Код: plsql
1.
2.
3.
4.
5.
6.
MERGE INTO Книги
USING (select rownum as x, id from Книги where Полка = 1 order by id asc) z
ON (Книги.IDКниги = z.IDКниги)
WHEN MATCHED 
THEN UPDATE 
 SET Книги.НомерКнигиНаПолке = z.x + count;



И в конце, перемещаем книги на полку 1:
Код: plsql
1.
2.
3.
4.
5.
6.
MERGE INTO Книги
USING (select rownum as x, id from Книги where id in (4,5) order by id asc) z
ON (Книги.IDКниги = z.IDКниги)
WHEN MATCHED 
THEN UPDATE 
 SET Книги.НомерКнигиНаПолке = z.x, Книги.НомерПолки = 1;




Меня не устраивает локанничность при перемещении в начало полки.
Можно ли как то это записать одним запросом?
...
Рейтинг: 0 / 0
31.01.2018, 11:05
    #39593775
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
iv_roman_vlУ каждой книги на полке есть свое место(номер места).rownum тут не к месту.
Поставить в конец - номер=max+1.
Вытащить - номер=номер-1 для номеров с убранного.
Вставить номер=номер+1 для номеров с вставленного.
...
Рейтинг: 0 / 0
31.01.2018, 11:59
    #39593826
MaximaXXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
iv_roman_vl,

1. не стоит использовать названия переменных такие же как и имена команд, и читать сложно, и проблемы могут возникнуть (into count)
2. не нашел перерасчет полки с которой сняли книги для "вставки в начало" ... если полка останется не сортированной на нее книги вернуть будет сложно
3. Для вставки в начало, я бы вставил записи с НомерКнигиНаПолке = 0 и прогнал один раз перенумерацию с сортировкой order by НомерКнигиНаПолке, id
...
Рейтинг: 0 / 0
31.01.2018, 12:25
    #39593846
Dshedoo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
В процедуру надо передавать ID книг и их новые полки (new_polka) и места (new_mesto).
1) В курсоре выбираем книгу.
2) Запихиваем в old_polka и old_mesto текущее положение книги.
3) Апдейтим все книги на new_polke, у которых mesto >= new_mesto. set mesto = mesto+1
4) Апдейтим все книги на old_polke, у которых mesto > old_mesto. set mesto = mesto - 1.
5) Апдейтим книгу set mesto = new_mesto, polka = new_polka
...
Рейтинг: 0 / 0
31.01.2018, 12:28
    #39593851
Dshedoo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
DshedooВ процедуру надо передавать ID книг и их новые полки (new_polka) и места (new_mesto).
1) В курсоре выбираем книгу.
2) Запихиваем в old_polka и old_mesto текущее положение книги.
3) Апдейтим все книги на new_polke, у которых mesto >= new_mesto. set mesto = mesto+1
4) Апдейтим все книги на old_polke, у которых mesto > old_mesto. set mesto = mesto - 1.
5) Апдейтим книгу set mesto = new_mesto, polka = new_polka
Выполнять пункты в такой последовательности: 1 - 2 - 3 - 5 - 4
...
Рейтинг: 0 / 0
31.01.2018, 13:27
    #39593908
iv_roman_vl
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
DshedooВ процедуру надо передавать ID книг и их новые полки (new_polka) и места (new_mesto).
1) В курсоре выбираем книгу.
2) Запихиваем в old_polka и old_mesto текущее положение книги.
3) Апдейтим все книги на new_polke, у которых mesto >= new_mesto. set mesto = mesto+1
4) Апдейтим все книги на old_polke, у которых mesto > old_mesto. set mesto = mesto - 1.
5) Апдейтим книгу set mesto = new_mesto, polka = new_polka

Я так понимаю, что если у нас перемещаются три книги, то действия 2,3,4,5 будут повторятся по три раза.
Этот вариант хорошо подходит если у нас книга может, например из центра полки переместится в другой центр полки.

У меня такого случая быть не может.
У меня книги строго, либо в конец либо в начало. А старая полка в порядке очередности просто пересчитывается. То есть книги на старой полке просто "сдвинули" друг к другу.

И предложенный вариант будет избыточный, так как надо будет пункты 2,3,4,5 повторять для каждой книги.

Все равно спасибо за участие.
Я понял, что мой метод имеет место быть.

Просто меня интересовало, могу ли я два запроса(1-й пересчет от количества перемещаемых книг, 2 - пересчет перемещаемых книг) при перемещении в голову обьеденить в один. Видимо нет. Но все равно всем спасибо.

PS: про имя into count знаю. Спасибо!
...
Рейтинг: 0 / 0
31.01.2018, 14:00
    #39593943
MaximaXXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
iv_roman_vlПросто меня интересовало, могу ли я два запроса(1-й пересчет от количества перемещаемых книг, 2 - пересчет перемещаемых книг) при перемещении в голову обьеденить в один. Видимо нет.

Ну от чего же сразу нет.

Можно написать 1 мердж который основан на сортировке НомерКнигиНаПолке а потом ID по передаваемому значению НомерПолки.

А вставка будет апдейтить НомерПолки на нужную, в начало меняет НомерКнигиНаПолке = 0 для вставляемых книг
в конец меняет НомерКнигиНаПолке переводит в null

После запускаем наш единственный мердж который и пересчитает НомерКнигиНаПолке для старой а потом и для новой полки.
...
Рейтинг: 0 / 0
31.01.2018, 14:02
    #39593946
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
iv_roman_vl,

перемещения в "однопользовательском" режиме?


ps
Вы хотите одним merge убрать книги из полки и положить на другую с перенумерациями?
или оператора два - один знимает книги с полки, другой кладет с перенумерациями?
.....
stax
...
Рейтинг: 0 / 0
31.01.2018, 14:39
    #39594015
iv_roman_vl
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
Staxiv_roman_vl,

перемещения в "однопользовательском" режиме?


ps
Вы хотите одним merge убрать книги из полки и положить на другую с перенумерациями?
или оператора два - один знимает книги с полки, другой кладет с перенумерациями?
.....
stax

Да, в однопользовательском.
Да, одним merge.
...
Рейтинг: 0 / 0
31.01.2018, 15:00
    #39594048
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
iv_roman_vl,

книги снимаются с одной полки, или могут сниматся сразу из нескольких?
все снятые книги ставятся на одну конкретную полку?

.....
stax
...
Рейтинг: 0 / 0
31.01.2018, 15:09
    #39594063
iv_roman_vl
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
Staxiv_roman_vl,

книги снимаются с одной полки, или могут сниматся сразу из нескольких?
все снятые книги ставятся на одну конкретную полку?

.....
stax

За одну операцию(одного нажатии на кнопку переместить)
Книги снимаются только с одной полки. И ставятся только на одну полку(строго либо в начало полки, либо в конец).

И вопрос в том можно ли сделать перенос книг с одной полки на другую, с соответствующим пересчетом на обеих полках,
при вставке в начало полки,
одним запросом.
...
Рейтинг: 0 / 0
31.01.2018, 15:22
    #39594079
MaximaXXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
iv_roman_vl,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
/*drop table books;
create table books (id number(10), rack number(10), numOfRack number(10));
insert into books (id, rack, numOfRack) values (1,1,1);
insert into books (id, rack, numOfRack) values (2,1,2);
insert into books (id, rack, numOfRack) values (3,1,3);
insert into books (id, rack, numOfRack) values (4,2,1);
insert into books (id, rack, numOfRack) values (5,2,2);
insert into books (id, rack, numOfRack) values (6,2,3);
*/

select row_number() over (partition by case when id in (1,2) then 2/*new rack*/ else rack end
                          order by 
                          case when id in (1,2) then 2/*new rack*/ else rack end, 
                          case when id in (1,2) then decode(2/*1 - at first*/,1,0) else numOfRack end,
                          id) new_numOfRack, 
                          id, case when id in (1,2) then 2/*new rack*/ else rack end new_rack
                          
from books
--where rack in (1,2)

order by new_numOfRack
...
Рейтинг: 0 / 0
31.01.2018, 15:26
    #39594087
MaximaXXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
Это я перевожу книги 1 и 2 с полки 1 на полку 2 перерасчитывая две полки (ну их всего две )


где:
Код: plsql
1.
decode(2/*1 - at first*/,1,0)

- 1 - с начала, 2-ка например с конца
Код: plsql
1.
2/*new rack*/

- полка на которую перенесли
...
Рейтинг: 0 / 0
31.01.2018, 15:45
    #39594107
Dshedoo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
iv_roman_vlStaxiv_roman_vl,

книги снимаются с одной полки, или могут сниматся сразу из нескольких?
все снятые книги ставятся на одну конкретную полку?

.....
stax

За одну операцию(одного нажатии на кнопку переместить)
Книги снимаются только с одной полки. И ставятся только на одну полку(строго либо в начало полки, либо в конец).

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

Так вот "одной кнопкой" ты можешь вызывать процедуру, которая и будет делать всё, что я описал ранее.
Правильнее реализовывать не тот подход, который решает конкретную задачу, а тот, который будет универсален, и будет, в том числе, решать конкретную задачу.
...
Рейтинг: 0 / 0
31.01.2018, 16:00
    #39594120
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
iv_roman_vl,

влоб
Код: 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.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
SQL> select * from t order by p,n;

        ID          P          N
---------- ---------- ----------
         1          1          1
         2          1          2
         3          1          3
         4          2          1
         5          2          2
         6          2          3
         7          2          4

7 rows selected.

SQL> print :t_in

      T_IN
----------
         1

SQL> MERGE INTO t
  2  USING (
  3  select
  4    k.*
  5   ,row_number() over (partition by p order by srt,n) rn
  6  from
  7   (select id,p,n,1 srt from t where p=:t_in --старые книги
  8    union all
  9    select id,:t_in,n,0 srt from t where id in (4,5) -- добавленные (0- в начало  2- в конец)
 10    union all
 11    select id,p,n,1 srt from t where id not in (4,5)
 12                        and p=(select min(p) from t where id in (4,5)) -- без снятих
 13   ) k
 14  ) z
 15  ON (t.ID = z.ID)
 16  WHEN MATCHED
 17  THEN UPDATE
 18   SET t.p=z.p, n=z.rn
 19  /

7 rows merged.

SQL> select * from t order by p,n;

        ID          P          N
---------- ---------- ----------
         4          1          1
         5          1          2
         1          1          3
         2          1          4
         3          1          5
         6          2          1
         7          2          2

7 rows selected.

SQL> rollback;

Rollback complete.

SQL> ed
Wrote file afiedt.buf

  1  MERGE INTO t
  2  USING (
  3  select
  4    k.*
  5   ,row_number() over (partition by p order by srt,n) rn
  6  from
  7   (select id,p,n,1 srt from t where p=:t_in --старые книги
  8    union all
  9    select id,:t_in,n,2 srt from t where id in (4,5) -- добавленные (0- в начало  2- в конец)
 10    union all
 11    select id,p,n,1 srt from t where id not in (4,5)
 12                        and p=(select min(p) from t where id in (4,5)) -- без снятих
 13   ) k
 14  ) z
 15  ON (t.ID = z.ID)
 16  WHEN MATCHED
 17  THEN UPDATE
 18*  SET t.p=z.p, n=z.rn
SQL> /

7 rows merged.

SQL> select * from t order by p,n;

        ID          P          N
---------- ---------- ----------
         1          1          1
         2          1          2
         3          1          3
         4          1          4
         5          1          5
         6          2          1
         7          2          2

7 rows selected.

SQL> rollback;

Rollback complete.

SQL>



....
stax
...
Рейтинг: 0 / 0
31.01.2018, 16:52
    #39594167
iv_roman_vl
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
Stax,

Спасибо, это именно то что нужно!!!!!!!!!!!!!!!!!!

Скрипт ОГОНЬ!!!

ОГРОМНЫЙ РЕСПЕКТ!!!

чувствую как мой скил прокачался!!!!
...
Рейтинг: 0 / 0
31.01.2018, 17:04
    #39594183
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
iv_roman_vl,

можно сделать и оптимальнее (без/меньше union all), условие выборки будет запутанее

делал влоб, чтоб понятнее было

ps
снятие книг с нескольких полок одновременно
p in (select p from t where id in (4,5))


.....
stax
...
Рейтинг: 0 / 0
01.02.2018, 08:42
    #39594592
iv_roman_vl
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
select в updete вставить rownum
Stax,

Да, спасибо! Принцип понял.
Пока с нескольких полок не требуется.
Но возьму на вооружение.
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / select в updete вставить rownum / 24 сообщений из 24, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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