I have a column store table, TABLE_HANA with the below data in HANA DB:
T_ID1 T_ID2 T_DESC T_RN
1 1 AAA ?
1 1 BBB ?
1 2 CCC ?
1 3 DDD ?
1 3 EEE ?
I need to group them by T_ID1 and T_ID2 and update the T_RN column of that group with a sequential value as shown below:
T_ID1 T_ID2 T_DESC T_RN
1 1 AAA 1
1 1 BBB 2
1 2 CCC 1
1 3 DDD 1
1 3 EEE 2
Since the table is very huge(millions of records), I am looking for a solution with good performance. Please suggest.
TIA
The first question is whether you really need to do the update. The following query returns what you want:
select h.*,
row_number() over (partition by t_id1, t_id2 order by t_desc) as t_rn
from table_hana h;
This may be sufficient.
The update will probably be expensive:
update table_hana h
set t_rn = (select count(*)
from table_hana h2
where h2.t_id1 = h.t_id1 and h2.t_id2 = h.t_id2 and h2.desc <= h.desc
);
An index on table_hana(t_id1, t_id2, t_desc) should help both these queries.
Related
Re-edited to make it clearer:
I would like my results to appear as they do in 'Column b' based on 'Column a' groupings? so a 1 or 0 per group based on column a. Column b does not exist currently, I am trying to code this in. I was trying to use row_number or rank but this not appear to work for me. So how do I write my SQL so I can get my SQL results to mirror Column b? Any help is appreciated
Thank - you
column a
column b
aaa
1
aaa
0
ddd
1
ddd
0
ddd
0
yyy
1
yyy
0
yyy
0
You just need to wrap your row_number() in a case, something like this:
select
column_a
case row_number() over (partition by column_a)
when 1 then 1
else 0
end as column_b
from
table
/
I have this table with the following records:
table1
id ele_id_1 ele_val ele_id_2
1 2 123 1
1 1 abc 1
1 4 xyz 2
1 4 456 1
2 5 22 1
2 4 344 1
2 3 6 1
2 2 Test Name 1
2 1 Hello 1
I am trying to add position for each id when ele_id_1 and ele_id_2 is order by ASC.
Here is the output:
id ele_id_1 ele_val ele_id_2 position
1 2 123 1 2
1 1 abc 1 1
1 4 xyz 2 4
1 4 456 1 3
2 5 22 1 5
2 4 344 1 4
2 3 6 1 3
2 2 Test Name 1 2
2 1 Hello 1 1
I have 34 million rows in table1, so would like to use an efficient way of doing this.
Any idea on how I can add position with values?
I think you want row_number() used like this:
select row_number() over (partition by id
order by ele_id_1, ele_id_2
) as position
Oracle can use an index for this, on (id, ele_id_1, ele_id_2).
I should note that for your example data order by ele_id_1, ele_id_2 and order by ele_id_2, ele_id_1 produce the same result. Your question suggests that you want the first.
So, you would get
id ele_id_1 ele_val ele_id_2 position
1 1 123 2 2
1 1 abc 1 1
1 4 xyz 2 4
1 4 456 1 3
Rather than:
id ele_id_1 ele_val ele_id_2 position
1 1 123 2 3
1 1 abc 1 1
1 4 xyz 2 4
1 4 456 1 2
EDIT:
If you want to update the data, then merge is probably the best approach.
MERGE INTO <yourtable> dest
USING (select t.*,
row_number() over (partition by id
order by ele_id_1, ele_id_2
) as new_position
from <yourtable> t
) src
ON dest.id = src.id AND
dest.ele_id_1 = src.ele_id_1 AND
dest.ele_id_2 = src.ele_id_2
WHEN MATCHED THEN UPDATE
SET desc.postition = src.new_position;
Note that updating all the rows in a table is an expensive operation. Truncating the table and recreating it might be easier:
create table temp_t as
select t.*,
row_number() over (partition by id
order by ele_id_1, ele_id_2
) as new_position
from t;
truncate table t;
insert into t ( . . . )
select . . . -- all columns but position
from temp_t;
However, be very careful if you truncate the table. Be sure to back it up first!
How can I add an identity number so that when a row is inserted an incremental number is assigned as below by a trigger? I am using SQL Server.
1 AAA
2 AAA
3 BBB
4 CCC
5 CCC
6 CCC
7 DDD
8 DDD
9 EEE
....
And I want to convert it to:
1 AAA 1
2 AAA 2
4 CCC 1
5 CCC 2
6 CCC 3
7 DDD 1
8 DDD 2
You could create a FUNCTION which get a name and gives MAX identity for given parameter:
CREATE FUNCTION [dbo].[GetIdentityForName] (#Name VARCHAR(MAX))
RETURNS INT
AS
BEGIN
RETURN
(SELECT ISNULL(MAX(NameId),0)+1
FROM YourTable
WHERE Name = #Name);
END
and then set DefaultValue for NameId for call the function when a record has been inserted like this:
ALTER TABLE YourTable ADD CONSTRAINT
DF_Identity_NameId DEFAULT ([dbo].[GetIdentityForName](Name)) FOR NameId
Assuming that YourTable is (Id, Name, NameId).
I hope to be helpful for you :)
There is no reason why you have to store the value. You could calculate it when you need it:
select t.*, row_number() over (partition by name order by id) as nameId
from t;
I have a table in the following format:
id Value
1 1
2 0.5
2 0.5
3 0.7
3 0.3
4 0.2
4 0.8
5 0
5 1
I want to update this table so I can get it in the following format:
id Value
1 1
2 1
3 1
4 1
5 1
Is there a way to update this without first updating all values to 1 and then removing the duplicate rows?
Try this:
select id,SUM(Value)
from myTable
group by id
order by id
try this,
update t
SET t.col = b.total
FROM t INNER JOIN
(select id,SUM(col) as total from t
group by id
) as b
ON t.id = b.id
Remove duplicate after this
delete from t
where id in(select id from t group by id having
count(*) >1)
http://sqlfiddle.com/#!3/c1e9f/13
I have the following problem.
Imagine I get the following return table from a select statement
Column A Column B
100 aaa
100 bbb
100 ccc
200 ddd
300 eee
So the question is, how can I change my SQL Select statement to add a new column that shows the numbers of times the Column A has a repeat value. The problem is that I need to get some subgrups with an order.
For example, it should return something like:
Column A Column B Column C
100 aaa 1
100 bbb 2
100 ccc 3
200 ddd 1
300 eee 1
Thank you very much for your support!
This is the classic usecase for the analytic RANK() function:
SELECT a, b, RANK() OVER (PARTITION BY a ORDER BY b) AS c
FROM my_table
Add ROW_NUMBER() OVER (PARTITION BY ColA ORDER BY SomethingElse) as ColC. That gives you a sequential row number per "group" in ColA.