Oracle column number increase - sql

I would like to know how to increase the row number by 1 in Column 1 when Column 2 value changes in Oracle
What I am looking for is to achieve this :
COL1 COL2 COL3 |
1 2000 xx |
1 2000 xy |
1 2000 xyz |
2 3020 x |
2 3020 xiii |
3 5666666 ueueu
Any idea ?

I think you are looking for a window function:
select row_number() over (partition by col2 order by col3) as col1,
col2,
col3
from the_table;

If you want to increase col1 value after updating col2 on table t_ then you can use trigger.
CREATE OR REPLACE TRIGGER upcol1
AFTER UPDATE ON t_ FOR EACH ROW
WHEN (old.col2 != new.col2)
BEGIN
UPDATE t_ SET col1=:new.col1+1
WHERE col2=:new.col2 AND col3=:new.col3;
END;

Related

Select query eliminating unwanted rows

I'm new to SQLite and I am having trouble finding the solution.
I have TABLE1 with columns col1 and col2
col1 col2
-------------
a no
a no
a yes
b no
c yes
c no
d yes
I want no repetitions from col1 but prioritize col2 when having "yes"
I want something like this
col1 col2
-------------
a yes
b no
c yes
d yes
You may try the following:
Approach 1
You may use row_number to retrieve a row number ordered by col2 in descending order that may be used to filter your results eg.
SELECT
col1,
col2
FROM (
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY col1
ORDER BY col2 DESC
) rn
FROM
my_table
) t
WHERE rn=1;
col1
col2
a
yes
b
no
c
yes
d
yes
Approach 2
or simply use a group by col1 with the MAX function. The group by will ensure that for each col1 value you will receive the MAX of col2 that is yes if available and no if not.
SELECT
col1,
MAX(col2) as col2
FROM
my_table
GROUP BY
col1;
col1
col2
a
yes
b
no
c
yes
d
yes
View working demo on DB Fiddle
ggordon's answer will work well enough, but just since a window function isn't strictly necessary I figured I'd pass another solution:
select distinct
a.col1,
ifnull(b.col2, 'no') col2
from my_table a
left join (
select distinct
col1,
col2
from my_table
where col2 = 'yes'
) b on a.col1 = b.col1
Output:
| col1 | col2 |
| ---- | ---- |
| a | yes |
| b | no |
| c | yes |
| d | yes |
You will first want to do a distinct select on column one. Then you will want to make a case statement which is essentially a if statement in other languages. The case needs to be if column 1 is yes return it. if it is not yes then return no. It would look something like this
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
WHEN conditionN THEN resultN
ELSE result
END;

Update column value in all rows of a table on mod(rownum,10) = number

I have a table tab1 that looks like this:
col1 | col2 | col3
------|------|------
abc | 100 | text
abc | 100 | text
abc | 100 | text
... | ... | ...
I need to update col2 value in each row like this:
update tab1
set col2 = 1,23
when mod(rownum,10) = 1;
update tab1
set col2 = 12,34
when mod(rownum,10) = 2;
update tab1
set col2 = 123,45
when mod(rownum,10) = 3;
and etc. until when mod(rownum,10) = 9.
But obviously this query doesn't work, and the reason is that rownum always returns 1 in this situation, afaik. However, I've got the correct last digits for each row number with select mod(rownum,10) as lastDig from tab1 query. But I don't understand how to use the result of this select for my update when conditions.
Could you please provide an example of a query that will do the job in this situation? Do I need to use a subquery or select in a temporary table? Please explain. I'm a junior frontend guy, but I need to create a demo table this way. I believe, pl/sql is v10, as well as PL/SQL Developer.
Result wanted looks like this:
col1 | col2 | col3
------|-------|------
abc | 1.23 | text
abc | 12.34 | text
abc | 123.45| text
... | ... | ...
You could use CASE expression or DECODE:
update tab1
set col2 = CASE mod(rownum,10) WHEN 1 THEN 1.23
WHEN 2 THEN 12.34
WHEN 3 THEN 123.45
-- ...
ELSE col2
END
-- WHERE ...
UPDATE tab1
SET col2 = DECODE(mod(rownum,10), 1, 1.23, 2, 12.34, 3, 123.45, ..., col2)
-- WHERE ...;
DBFiddle Demo
You have not told us if there is a specific order in which you want to treat rows as 1,2,3 .. If there is indeed an order, then ROWNUM is unreliable and may not work, you would need row_number() with a specific order by column. That can be combined with a MERGE statement.
MERGE INTO tab1 tgt USING (
SELECT
CASE mod( ROW_NUMBER() OVER(
ORDER BY
col1 -- the column which is in order and unique
),10)
WHEN 1 THEN 1.23
WHEN 2 THEN 12.34
WHEN 3 THEN 123.45
--..
--.. 9
ELSE col2
AS col2
FROM
tab1 t
)
src ON ( tgt.rowid = src.rowid ) --use primary key/unique key if there is one instead of rowid
WHEN MATCHED THEN UPDATE SET tgt.col2 = src.col2;
Demo

Selecting rows based on latest timestamp

I have a question about tables, as I am new to it if any help that would be great.
I have a table with 3 columns. I use the first column out of it to make it as the common key. Based on the key I may get multiple rows selected. I would like to select the row with the latest timestamp which is column 2. Column 3 can have different values.
Eg:
Col1 Col2 Col3
some_name 12:5:12 1
some_name 12:6:12 0
some_name1 12:5:12 1
some_name1 12:6:12 0
some_name2 12:5:12 0
some_name2 12:6:12 1
Output:
Col1 Col2 Col3
some_name 12:6:12 0
some_name1 12:6:12 0
some_name2 12:6:12 1
I would like to do this in apache spark.
In Spark, I think I would go for row_number():
select t.*
from (select t.*, row_number() over (partition by col1 order by col2 desc) as seqnum
from t
) t
where seqnum = 1;
Using sparks Window functions:
val w = Window.partitionBy("col1").orderBy(col("col2").desc)
df.withColumn("latestTS", row_number().over(w))
.where(col("latestTS") === 1)
.drop("latestTS")
.show(false)
+----------+-------+----+
|col1 |col2 |col3|
+----------+-------+----+
|some_name |12:6:12|0 |
|some_name1|12:6:12|0 |
|some_name2|12:6:12|1 |
+----------+-------+----+
this query may help you
select
*
from table ta
where ta.col2 = (select MAX(col2) from table where col1 = ta.col1)
this query returan latest data for col1

How to deal with subquery which returns more than one value

Here is my table:
+----+------+------+
| ID | Col1 | Col2 |
+----+------+------+
| 11 | 156 | 48 |
| 12 | 5 | 22 |
| 13 | 156 | 32 |
+----+------+------+
What I want to do is
SELECT ID FROM Table1 WHERE Col1 = (SELECT MAX(col1) FROM Table1)
but since it will be declared and this is written inside a stored procedures that's will give an error that "Subquery returned more than 1 value".
If this error happens I want use 11 AND 12 and select Min(col2) of just those id then just give one ID.
Is it possible to catch the two ID's ? If yes how can I do this ?
Alternate answer which will work basically on every DB. (Just use LIMIT instead of TOP on some cases)
SELECT TOP 1 ID FROM Table1 ORDER BY Col1 DESC, Col2 ASC
Last time edit: I notice your sql-server tag. However this will work on postgre :(
This will give you the exact answer you are looking for.
SELECT DISTINCT ON (Col1) ID
FROM Table1
WHERE Col1 = (SELECT MAX(col1) FROM Table1)
ORDER BY Col2 ASC

insert thousands of rows in DB2

I need to multiply a certain row in a DB2 table 18000 times. Some of the column values will remain as the original and some need to be incremented by 1.
I have very little knowledge in DB2 and I just can't find a concrete simple answer on how to do this. Can someone please give me an example on how to achieve this?
DB2 version: 9.7 / OS: Windows 2k8
For example I have the following table:
T_RES_TABLE
Col1 |Col2|Col3 |Col4|
----------------------
1 | 1| 1| 1|
What I need to achieve is:
T_RES_TABLE
Col1 |Col2|Col3 |Col4|
----------------------
1 | 1| 1| 1| - original
----------------------
2 | 1| 2| 1|
----------------------
.
.
.
----------------------
18000| 1|18000| 1|
So Col1 and Col3 need to increment and the rest must stay as is. Hope it's clear enough.
You can use a recursive query to generate new column values:
$ db2 "create table t_res_table (col1 int, col2 int, col3 int, col4 int)"
DB20000I The SQL command completed successfully.
$ db2 "insert into t_res_table values (1,1,1,1)"
DB20000I The SQL command completed successfully.
$ db2 "select * from t_res_table"
COL1 COL2 COL3 COL4
----------- ----------- ----------- -----------
1 1 1 1
1 record(s) selected.
$ db2 "insert into t_res_table \
>with t (col1, col2, col3, col4, lvl) as ( \
>select col1, col2, col3, col4, 1 from t_res_table where col1 =1 \
>union all \
>select col1+1, col2, col3+1, col4, lvl+1 from t where lvl <18) \
>select col1, col2, col3, col4 from t where col1 > 1"
DB20000I The SQL command completed successfully.
$ db2 "select * from t_res_table"
COL1 COL2 COL3 COL4
----------- ----------- ----------- -----------
1 1 1 1
2 1 2 1
3 1 3 1
4 1 4 1
5 1 5 1
6 1 6 1
7 1 7 1
8 1 8 1
9 1 9 1
10 1 10 1
11 1 11 1
12 1 12 1
13 1 13 1
14 1 14 1
15 1 15 1
16 1 16 1
17 1 17 1
18 1 18 1
18 record(s) selected.
This will do your job. Just change it as your needs, change table name and column names and hit run.
I dont know what you want to achieve but, it sounds you just need an Dummy Data in a table. So, i just make it for dummy purpose.
Modify it for your another requirements. The example below contains everything what you need, but you may have to modify according to that.
DECLARE #I INT=0
SET #I=1
DECLARE #LASTF2 INT
DECLARE #LASTF4 INT
SELECT #LASTF2=ISNULL(MAX(F2),1) FROM TEST --JUST CHANGE TEST TO YOUR TABLENAME, AND F1,F2,F3,F4
SELECT #LASTF4=ISNULL(MAX(F4),1) FROM TEST -- AS YOUR FIELD NAMES
WHILE #I<10000
BEGIN
INSERT INTO TEST (F1,F2,F3,F4)
VALUES (#I,#LASTF2,#I,#LASTF4)
SET #I=#I+1
END
GO
SELECT * FROM TEST