Updating postgres column with sequence of integers [duplicate] - sql

This question already has answers here:
SQL update records with ROW_NUMBER()
(2 answers)
Closed 1 year ago.
I have a postgres table bar that contains 130 rows. I would like to auto-populate the id column with a sequence of incrementing integers from 1 to 130. When I try the following code:
update bar
set id = t.num FROM (
SELECT *
FROM generate_series(1, 130) num) t
The column is updated but every row contains 1. What I am doing wrong here and what is the correct syntax for this procedure?

You need a primary key to identify each row. Then you can use:
update bar b
set id = b2.new_id
from (select b.*, row_number() over (order by id) as new_id
from bar
) b2;
where b.pk = b2.pk;
Your version is attempting to update each row 130 times. Only one update is kept -- seemingly the first one but you cannot depend on that.

Related

Deduplicate table while keeping the version vers column is not null

I have a table with 2 columns: an id and an associated label.
Example:
id1,label1
id1,null
id2,label2
id3,null
I would like to deduplicate on the 1st column to keep the version where the label column is not null. But if the id appears only once, I want to keep the line no matter what, even though the label is null.
The output I would want with the example is:
id1,label1
id2,label2
id3,null
How can I do this ?
Consider below (BigQuery)
select *
from your_table
qualify 1 = row_number() over(partition by id order by label desc)
if applied to sample data in your question - output is
Use EXISTS (see demo)
delete
from <table1> d1
where d1.label is null
and exists ( select null
from <table1> d2
where d2.id = d1.id
and d2.label is not null
) ;
EXISTS always returns True or False if the subslect would have returned at least 1 row. In this case it returns True only when there is a matching row where label is not null.
Note: This does not work where there are multiple id each having a non-null label nor each having a null label. So would not work on tuples
('a',null) with ('a',null) nor the tuples
('a','l1') with ('a','l1')

SQL Query : should return Single Record if Search Condition met, otherwise return Multiple Records

I have table with Billions of Records, Table structure is like :
ID NUMBER PRIMARY KEY,
MY_SEARCH_COLUMN NUMBER,
MY_SEARCH_COLUMN will have Numeric value upto 15 Digit in length.
What I want is, if any specific record is matched, I will have to get that matched value only,
i.e. : If I enter WHERE MY_SEARCH_COLUMN = 123454321 and table has value 123454321 then this only should be returned.
But if exact value is not matched, I will have to get next 10 values from the table.
i.e. : if I enter WHERE MY_SEARCH_COLUMN = 123454321 and column does not have the value 123454321 then it should return 10 values from the table which is greater than 123454321
Both the case should be covered in single SQL Query, and I have have to keep in mind the Performance of the Query. I have already created Index on the MY_SEARCH_COLUMN columns, so other suggestions are welcome to improve the Performance.
This could be tricky to do without using a proc or maybe some dynamic SQL, but we can try using ROW_NUMBER here:
WITH cte AS (
SELECT ID, MY_SEARCH_COLUMN,
ROW_NUMBER() OVER (ORDER BY MY_SEARCH_COLUMN) rn
FROM yourTable
WHERE MY_SEARCH_COLUMN >= 123454321
)
SELECT *
FROM cte
WHERE rn <= CASE WHEN EXISTS (SELECT 1 FROM yourTable WHERE MY_SEARCH_COLUMN = 123454321)
THEN 1
ELSE 10 END;
The basic idea of the above query is that we assign a row number to all records matching the target or greater. Then, we query using either a row number of 1, in case of an exact match, or all row numbers up to 10 in case of no match.
SELECT *
FROM your_table AS src
WHERE src.MY_SEARCH_COLUMN = CASE WHEN EXISTS (SELECT 1 FROM your_table AS src2 WITH(NOLOCK) WHERE src2.MY_SEARCH_COLUMN = 123456321)
THEN 123456321
ELSE src.MY_SEARCH_COLUMN
END

ORACLE SQL: how to update a table based in another column? [duplicate]

This question already has answers here:
Oracle SQL: Update a table with data from another table
(7 answers)
Closed 6 years ago.
So, i have two tables, INTERNAMENTO and DOC_ADMISSAO2. i want to update a column from table INTERNAMENTO named DIASINTERNAMENTO with the same values of the table DOC_ADMISSAO2 called DIASADMISSAO, with some conditions..
update INTERNAMENTO a
set a.DIASINTERNAMENTO = (
select b.DIASADMISSAO
from DOC_ADMISSAO2 b
where (a.EPISODIO = b.EPISODIO) AND (a.DATACRIACAO <= b.DATACRIACAO));
It gives me an error:
00000 - "single-row subquery returns more than one row"
Any advice?
The error is quite clear. The subquery is returning more than one row. You can get one row by either adding and rownum = 1 or adding an aggregation function:
update INTERNAMENTO a
set DIASINTERNAMENTO = (
select max(b.DIASADMISSAO)
from DOC_ADMISSAO2 b
where (a.EPISODIO = b.EPISODIO) AND (a.DATACRIACAO <= b.DATACRIACAO)
);
If you happen to want the most recent value of DISASMISSAO for the EPISODIO based on DATACRIACAO, then you can use keep:
update INTERNAMENTO a
set DIASINTERNAMENTO = (
select max(b.DIASADMISSAO) keep (dense_rank first order by b.DATACRIACAO desc)
from DOC_ADMISSAO2 b
where (a.EPISODIO = b.EPISODIO) AND (a.DATACRIACAO <= b.DATACRIACAO)
);
It means that there are multiple rows in doc_admissao2 for some value of internamento.episodio where b.datacriacao is greater than or equal to a.datacriacao.
To find out which ones, try something like this (untested):
SELECT a.episodio, count(*)
FROM internamento a JOIN doc_admissao2 b ON a.episodio = b.episodio
WHERE a.DATACRIACAO <= b.DATACRIACAO
GROUP BY a.episodio
HAVING count(*) > 1;

SQL set operation for update latest record

I am facing a problem and cant find any solution to this. I have a source table (T) where I get data from field. The data may contain duplicate records with time stamp. My objective is to take the field data and store it into a final table (F) having the same structure.
Before inserting I check whether key field exists or not in the F if yes I update the the record in F with the latest one from T. Other wise I Insert the record in F from T. This works fine as long as there is no duplicate record in T. In case T has two records of the same key with different time stamp. It always inserts both the record (In case the key is primary key the insert operation fails). I am using following code for the operation -
IF EXISTS(SELECT * FROM [Final_Table] F, TMP_Source T WHERE T.IKEy =F.IKEY)
begin
print 'Update'
UPDATE [Final_Table]
SET [FULLNAME] = T.FULLNAME
,[FATHERNAME] = T.FATHERNAME
,[MOTHERNAME] = T.MOTHERNAME
,[SPOUSENAME] = T.SPOUSENAME
from TMP_Source T
WHERE Final_Table.IKEy = T.IKEy
and [Final_Table].[RCRD_CRN_DATE] < T.RCRD_CRN_DATE
--Print 'Update'
end
else
begin
INSERT INTO [Final_Table]
([IKEy],[FTIN],[FULLNAME],[FATHERNAME],[MOTHERNAME],[SPOUSENAME]
)
Select IKEy,FTIN,FULLNAME,FATHERNAME,MOTHERNAME,SPOUSENAME
from TMP_Source
end
The problem comes when I my T table has entries like -
IKey RCRD_CRN_DATE ...
123 10-11-2013-12.20.30
123 10-11-2013-12.20.35
345 10-11-2013-01.10.10
All three are inserted in the F table.
Please help.
Remove all but the latest row as a first step (well, in a CTE) using ROW_NUMBER() before attempting to perform the insert:
;WITH UniqueRows AS (
SELECT IKey,RCRD_CRN_DATE,FULL_NAME,FATHER_NAME,MOTHER_NAME,SPOUSENAME,FTIN,
ROW_NUMBER() OVER (PARTITION BY IKey ORDER BY RCRD_CRN_DATE desc) as rn
FROM TMP_Source
)
MERGE INTO Final_Table t
USING (SELECT * FROM UniqueRows WHERE rn = 1) s
ON t.IKey = s.IKey
WHEN MATCHED THEN UPDATE
SET [FULLNAME] = s.FULLNAME
,[FATHERNAME] = s.FATHERNAME
,[MOTHERNAME] = s.MOTHERNAME
,[SPOUSENAME] = s.SPOUSENAME
WHEN NOT MATCHED THEN INSERT
([IKEy],[FTIN],[FULLNAME],[FATHERNAME],[MOTHERNAME],[SPOUSENAME]) VALUES
(s.IKEy,s.FTIN,s.FULLNAME,s.FATHERNAME,s.MOTHERNAME,s.SPOUSENAME);
(I may not have all the columns entirely correct, they seem to keep switching around in your question)
(As you may have noticed, I've also switched to using MERGE since it allows us to express everything as a single declarative statement rather than writing procedural code)

How to put consecutive numbers into table for SQL not one by one [duplicate]

This question already has answers here:
Generate an integer sequence in MySQL
(18 answers)
Closed 9 years ago.
Using below codes makes a table with one column as:
1
2
3
4
5
6
7
CREATE TABLE abc (a VARCHAR(8));
INSERT INTO abc VALUES(1),(2),(3),(4),(5),(6),(7)
But how we can use a method with using (1),(2),(3),(4),(5),(6),(7) , I mean something like 1:7 only?
Did anyone say recursion??
with rec as (
select 1 i
union all
select i+1 from rec where i < 7
)
select * from rec
If I am not wrong you are looking for a way to insert set of INT values in column in single batch. for example "insert 100 Identities in columnA."
there is no predefined SQL SERVER function for that. but you can work around using any system table that you sure will have sufficient number rows you are looking for.
SELECT rownum
FROM
(
SELECT name,ROW_NUMBER() OVER (ORDER BY name) rownum
FROM sysobjects so
)q
WHERE rownum <= 7