Oracle: UPDATE with ORDER BY [duplicate] - sql

I want to populate a table column with a running integer number, so I'm thinking of using ROWNUM. However, I need to populate it based on the order of other columns, something like ORDER BY column1, column2. That is, unfortunately, not possible since Oracle does not accept the following statement:
UPDATE table_a SET sequence_column = rownum ORDER BY column1, column2;
Nor the following statement (an attempt to use WITH clause):
WITH tmp AS (SELECT * FROM table_a ORDER BY column1, column2)
UPDATE tmp SET sequence_column = rownum;
So how do I do it using an SQL statement and without resorting to cursor iteration method in PL/SQL?

This should work (works for me)
update table_a outer
set sequence_column = (
select rnum from (
-- evaluate row_number() for all rows ordered by your columns
-- BEFORE updating those values into table_a
select id, row_number() over (order by column1, column2) rnum
from table_a) inner
-- join on the primary key to be sure you'll only get one value
-- for rnum
where inner.id = outer.id);
OR you use the MERGE statement. Something like this.
merge into table_a u
using (
select id, row_number() over (order by column1, column2) rnum
from table_a
) s
on (u.id = s.id)
when matched then update set u.sequence_column = s.rnum

UPDATE table_a
SET sequence_column = (select rn
from (
select rowid,
row_number() over (order by col1, col2)
from table_a
) x
where x.rowid = table_a.rowid)
But that won't be very fast and as Damien pointed out, you have to re-run this statement each time you change data in that table.

First Create a sequence :
CREATE SEQUENCE SEQ_SLNO
START WITH 1
MAXVALUE 999999999999999999999999999
MINVALUE 1
NOCYCLE
NOCACHE
NOORDER;
after that Update the table using the sequence:
UPDATE table_name
SET colun_name = SEQ_SLNO.NEXTVAL;

A small correction just add AS RN :
UPDATE table_a
SET sequence_column = (select rn
from (
select rowid,
row_number() over (order by col1, col2) AS RN
from table_a
) x
where x.rowid = table_a.rowid)

Related

Cannot recognize input near 'DELETE' 'FROM' 'CTE' in statement

I want to drop duplicates in mytable if there are identical value in col1.
WITH CTE AS
(
SELECT
*, ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col1) AS RN
FROM
mytable
)
DELETE FROM CTE
WHERE RN <> 1
I got error:
Cannot recognize input near 'DELETE' 'FROM' 'CTE' in statement
I don't think Hive supports that syntax for DELETE. Try this:
DELETE FROM mytable t
WHERE t.id > (SELECT MIN(t2.id) -- some sort of unique id
FROM t t2
WHERE t2.id = t.id
);
If you have complete duplicates, then the above won't work. In the most recent versions of Hive you can use MERGE. In older versions:
create table temp_t as
select distinct t.*
from t;
truncate table t;
insert into t
select * from temp_t;
Of course, backup the table before trying this!
Alternative way: assuming you have UNIQUE ID Column.
Delete from MyTable where ID in
(SELECT ID FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col1) AS RN
FROM mytable) a where RN <> 1)

Multiple statements with one cte?

What is the correct syntax for the following? (I need these in one query)
--- 1. task
update A set .... where ....
insert into A (...) values (...);
--- 2 .task
With cte as (select A.column...)
update A set ... if condition1(includes cte table)
update A set ... if condition2(includes cte table)
update A set ... if condition3(includes cte table)
In words:
I update table A or insert into it
After that I refer to this updated TableA in a cte table, which contains a ROW_NUMBER function,
And then I want to update TableA again depended on that rownumber from CTE in a specific row, for example: if rownumber value in the CTE is 1, do this, if it is max(rownumber) for that specific row then do that....
I read that cte-s only persist for a single statement. I tried to copy the cte for every update statement, separated with semicolons, but that didn't work. I read about MERGE but I'm not sure if this is the right way for that. Is it the OUTPUT clause, if yes, how to use it? Or something else? Can you help me please?
You don't need multiple update statement. You can do with one.
; WITH CTE as ( select . . . )
UPDATE A
SET col1 = case when .... then new_1 else col1 end,
col2 = case when .... then new_2 else col2 end
FROM CTE as A
For anyone who tries to avoid copy-paste and wants to reuse some complex query from CTE to perform multiple statements, probably temporary table would work for you:
select A.column as AnyColumn, ... into #NameYouWant from A, ...
update A set column1 = (select AnyColumn from #NameYouWant where ...)
update B set column2 = (select AnyColumn from #NameYouWant where ...)
update C set column3 = (select AnyColumn from #NameYouWant where ...)
Please note that number sign (#) in table name is important, it will indicate that table is temporary, so it would persist only within your current session.
Correct, a CTE only persists in the statement it exists in. Therefore a statement like the following will fail:
WITH CTE AS(
SELECT *,ROW_NUMBER() OVER (PARTITION BY Date ORDER BY ID) AS RN
FROM YourTable)
SELECT *
FROM CTE
WHERE RN = 1;
SELECT *
FROM CTE
WHERE RN = 2;
That's because the CTE no longer exists during the second statement.
For an UPDATE (or any statement ) you'll therefore need to redeclare your CTE each time. Thus, using the example above, you would have to do:
WITH CTE AS(
SELECT *,ROW_NUMBER() OVER (PARTITION BY Date ORDER BY ID) AS RN
FROM YourTable)
SELECT *
FROM CTE
WHERE RN = 1;
WITH CTE AS(
SELECT *,ROW_NUMBER() OVER (PARTITION BY Date ORDER BY ID) AS RN
FROM YourTable)
SELECT *
FROM CTE
WHERE RN = 2;
If the expressions within the CTE are quite complex, and you use them often, you might instead consider using a VIEW.

sql server duplicate ID's update other columns

I was working on a task to update columns which have duplicate ID's in a column
how can we update column only DrugLabelName ? i need to update old_drug_name with new_drug_name using the duplicate ID 00004029830 ?
Please advise
If you want all rows with the same id to have the same name, you can use window functions:
with toupdate as (
select t.*,
first_value(druglabelname) over (partition by id order by intid desc) as new_druglabelname
from t
)
update toupdate
set druglabelname = new_druglabelname
where druglabelname <> new_druglabelname;
How about?
CREATE TABLE tbl
(INTid int
,ID varchar (20)
,DrugLabelName varchar(200)
)
INSERT tbl (INTid, ID, DrugLabelName)
SELECT 137272, '00004029830', 'old_drug_name'
INSERT tbl (INTid, ID, DrugLabelName)
SELECT 1668177, '00004029830', 'New_drug_name'
INSERT tbl (INTid, ID, DrugLabelName)
SELECT 1668178, '00004029831', 'Other_drug_name'
GO
UPDATE t
SET DrugLabelName = x.DrugLabelName
FROM tbl AS t
INNER JOIN tbl as x
ON t.ID = x.id
AND x.INTid > t.INTid
SELECT *
FROM tbl
DROP TABLE tbl

PostgreSQL how to delete duplicated values

I have a table in my Postgres database where I forgot to insert a unique index. because of that index that i have now duplicated values. How to remove the duplicated values? I want to add a unique index on the fields translationset_Id and key.
I think you are asking for this:
DELETE FROM tablename
WHERE id IN (SELECT id
FROM (SELECT id,
ROW_NUMBER() OVER (partition BY column1, column2, column3 ORDER BY id) AS rnum
FROM tablename) t
WHERE t.rnum > 1);
It appears that you only want to delete records which are duplicate with regard to the translationset_id column. In this case, we can use Postgres' row number functionality to discern between duplicate rows, and then to delete those duplicates.
WITH cte AS
(
SELECT t.*, ROW_NUMBER() OVER (PARTITION BY translationset_id, key) AS rnum
FROM yourTable t
)
DELETE FROM yourTable
WHERE translationset_id IN (SELECT translationset_id FROM cte WHERE rnum > 1)
I think the most efficient way to do this is below.
DELETE FROM
table_name a
USING table_name b
WHERE
a.id < b.id and
a.same_column = b.same_column;
delete from mytable
where exists (select 1
from mytable t2
where t2.name = mytable.name and
t2.address = mytable.address and
t2.zip = mytable.zip and
t2.ctid > mytable.ctid
);

Oracle: Updating a table column using ROWNUM in conjunction with ORDER BY clause

I want to populate a table column with a running integer number, so I'm thinking of using ROWNUM. However, I need to populate it based on the order of other columns, something like ORDER BY column1, column2. That is, unfortunately, not possible since Oracle does not accept the following statement:
UPDATE table_a SET sequence_column = rownum ORDER BY column1, column2;
Nor the following statement (an attempt to use WITH clause):
WITH tmp AS (SELECT * FROM table_a ORDER BY column1, column2)
UPDATE tmp SET sequence_column = rownum;
So how do I do it using an SQL statement and without resorting to cursor iteration method in PL/SQL?
This should work (works for me)
update table_a outer
set sequence_column = (
select rnum from (
-- evaluate row_number() for all rows ordered by your columns
-- BEFORE updating those values into table_a
select id, row_number() over (order by column1, column2) rnum
from table_a) inner
-- join on the primary key to be sure you'll only get one value
-- for rnum
where inner.id = outer.id);
OR you use the MERGE statement. Something like this.
merge into table_a u
using (
select id, row_number() over (order by column1, column2) rnum
from table_a
) s
on (u.id = s.id)
when matched then update set u.sequence_column = s.rnum
UPDATE table_a
SET sequence_column = (select rn
from (
select rowid,
row_number() over (order by col1, col2)
from table_a
) x
where x.rowid = table_a.rowid)
But that won't be very fast and as Damien pointed out, you have to re-run this statement each time you change data in that table.
First Create a sequence :
CREATE SEQUENCE SEQ_SLNO
START WITH 1
MAXVALUE 999999999999999999999999999
MINVALUE 1
NOCYCLE
NOCACHE
NOORDER;
after that Update the table using the sequence:
UPDATE table_name
SET colun_name = SEQ_SLNO.NEXTVAL;
A small correction just add AS RN :
UPDATE table_a
SET sequence_column = (select rn
from (
select rowid,
row_number() over (order by col1, col2) AS RN
from table_a
) x
where x.rowid = table_a.rowid)