sql function to add each row values - sql

table a
id
1
2
3
4
i want output to be like this:
id id_new
1 1
2 3
3 6
4 10
basically we are adding row values of a column in each row
i.E 2=1+2 ,3=1+2+3 and so on
you can use any cursor,function or query

You seem to want a cumulative sum. The ANSI standard function is a window function, supported by Oracle:
select id, sum(id) over (order by id) as id_new
from t;
It seems strange to do this with a column called id, though. Usually, cumulative sums are on counts or amounts or something measurable.
If you need to actually update the data, then you can use a correlated subquery:
update t
set id_new = (select sum(id) from t t2 where t2.id <= t.id);
This will work on a small table. For anything larger, use merge.

The comment by Pradeep is probably the way to go on Oracle. But there is an alternative to that, which is using a correlated subquery to compute the rolling sum:
SELECT
id,
(SELECT SUM(t2.id) FROM yourTable t2 WHERE t2.id <= t1.id) id_new
FROM yourTable t1;
This answer may have some merit because not every database supports analytic functions. And even if we are using Oracle in the context of, e.g., a Java application, an ORM interface like JPA or Hibernate may not support analytic functions.

Piece of cake.
SQL> with test (id) as
2 (select 1 from dual union
3 select 2 from dual union
4 select 3 from dual union
5 select 4 from dual
6 )
7 select id, sum(id) over (order by id) id_new
8 from test
9 order by id;
ID ID_NEW
---------- ----------
1 1
2 3
3 6
4 10
SQL>
[EDIT, a generalized option]
SQL> select level id, sum(level) over (order by level) new_Id
2 from dual
3 connect by level <= &n;
Enter value for n: 5
old 3: connect by level <= &n
new 3: connect by level <= 5
ID NEW_ID
---------- ----------
1 1
2 3
3 6
4 10
5 15
SQL> /
Enter value for n: 3
old 3: connect by level <= &n
new 3: connect by level <= 3
ID NEW_ID
---------- ----------
1 1
2 3
3 6
SQL>

Related

How to use subquery to drop rows from Tab1 which are in Tab2 in Oracle SQL?

I have tables in Oracle SQL like below:
Tab1
ID
-----
1
2
3
Tab2
ID
-----
3
4
5
And I need to take values from Tab1 which are not in Tab2. I made query like below:
select ID
from Tab1
where ID not in (select ID from Tab2)
Above query does not work, how can I change it to achieve result as I need:
ID
---
1
2
I can add that I prefere to use subquery in this problem, how can I do that in Oracle SQL ?
With the MINUS set operator:
SQL> with
2 tab1 (id) as
3 (select 1 from dual union all
4 select 2 from dual union all
5 select 3 from dual
6 ),
7 tab2 (id) as
8 (select 3 from dual union all
9 select 4 from dual union all
10 select 5 from dual
11 )
12 select id from tab1
13 minus
14 select id from tab2;
ID
----------
1
2
SQL>
BTW, query you used (with a subquery) returns correct result; did you mean to say that you prefer NOT to use a subquery?
<snip>
12 select id from tab1
13 where id not in (select id from tab2);
ID
----------
1
2
I tried this code and it worked fine :
select ID
from Table1
where ID not in (select ID from Table2)
You cant DROP rows from a table, but you can DELETE them.
So correcting you title to
How to use subquery to DELETE rows from Tab1 which are in Tab2 in Oracle SQL?
do so:
delete from tab1
where id in (select id from tab2);
1 row deleted.
select * from tab1;
ID
----------
1
2
Do not forget to commit to make the change permanent.

how to select set of records is ID is present in one of them

Here is the table where ORGID/USERID makes unique combination:
ORGID USERID
1 1
1 2
1 3
1 4
2 1
2 5
2 6
2 7
3 9
3 10
3 11
I need to select all records (organizations and users) wherever USERID 1 is present. So USERID=1 is present in ORGID 1 and 2 so then select all users for these organizations including user 1 itself, i.e.
ORGID USERID
1 1
1 2
1 3
1 4
2 1
2 5
2 6
2 7
Is it possible to do it with one SQL query rather than SELECT *.. WHERE USERID IN (SELECT...
You could use exists:
select *
from mytable t
where exists (select 1 from mytable t1 where t1.orgid = t.orgid and t1.userid = 1)
Another option is window functions. In Postgres:
select *
from (
select t.*,
bool_or(userid = 1) over(partition by orgid) has_user_1
from mytable t
) t
where has_user_1
Or a more generic approach, that uses portable expressions:
select *
from (
select t.*,
max(case when userid = 1 then 1 else 0 end) over(partition by orgid) has_user_1
from mytable t
) t
where has_user_1 = 1
Yes, you can do it with a single select statement - no in or exists conditions, no analytic or aggregate functions in a subquery, etc. Why you want to do it that way is not clear; in any case, it is possible that the solution below is also more efficient than the alternatives. You will have to test on your real-life data to see if that is true.
The solution below has two potential disadvantages: it only works in Oracle (it uses a proprietary extension of SQL, the match_recognize clause); and it only works in Oracle 12.1 or higher.
with
my_table(orgid, userid) as (
select 1, 1 from dual union all
select 1, 2 from dual union all
select 1, 3 from dual union all
select 1, 4 from dual union all
select 2, 1 from dual union all
select 2, 5 from dual union all
select 2, 6 from dual union all
select 2, 7 from dual union all
select 3, 9 from dual union all
select 3, 10 from dual union all
select 3, 11 from dual
)
-- End of SIMULATED data (for testing), not part of the solution.
-- In real life you don't need the WITH clause; reference your actual table.
select *
from my_table
match_recognize(
partition by orgid
all rows per match
pattern (x* a x*)
define a as userid = 1
);
Output:
ORGID USERID
---------- ----------
1 1
1 2
1 3
1 4
2 1
2 5
2 7
2 6
You can use exists:
select ou.*
from orguser ou
where exists (select 1
from orguser ou ou2
where ou2.orgid = ou.orgid and ou2.userid = 1
);
Apart from Exists and windows function, you can use IN as follows:
select *
from your_table t
where t.orgid in (select t1.orgid from your_table t1 where t1.userid = 1)

THREE ROWS LEAD FUNCTION IN ORACLE PL SQL

My Table:
ID NAME
1 SIVA
2 RAJA
3 PYTHON
4 SQL
5 ODI
I need to lead by 3 rows.
My SQL Query:
SELECT LEAD(NAME,3) OVER (ORDER by NAME) as NAME FROM TEST_TABLE where NAME='SIVA'
EXPECTED OUTPUT:
--------
| NAME |
--------
| SQL |
--------
Example:
If I pass value as SIVA, then I need to get SQL as output.
Similarly if I pass value as Raja, then I need to get ODI as output
Is there any query to get the expected output?
This might be one option: it uses row_number analytic function which calculates row numbers so that you wouldn't have to rely on ID values. What if they are acquired by a sequence? It is not gapless. Basically - it is used for safety.
SQL> WITH test (id, name)
2 AS (SELECT 1, 'siva' FROM DUAL
3 UNION ALL
4 SELECT 2, 'raja' FROM DUAL
5 UNION ALL
6 SELECT 3, 'python' FROM DUAL
7 UNION ALL
8 SELECT 4, 'sql' FROM DUAL
9 UNION ALL
10 SELECT 5, 'odi' FROM DUAL),
11 temp AS (SELECT id, name, ROW_NUMBER () OVER (ORDER BY id) rn FROM test)
12 SELECT b.name
13 FROM temp a JOIN temp b ON b.rn = a.rn + 3
14 WHERE a.name = '&name';
Enter value for name: siva
NAME
------
sql
SQL> /
Enter value for name: raja
NAME
------
odi
SQL> /
Enter value for name: sql
no rows selected
SQL>
You can simply use sub-query :
SELECT Next_NAME
FROM (SELECT NAME, LEAD(NAME, 3) OVER (ORDER by id) AS Next_NAME
FROM TEST_TABLE
) t
WHERE NAME = 'SIVA';

Oracle logic to roll the value same level

I am facing issue is solving on oracle logic
I have below requirement, I have one table with Some Numbers and Corresponding ID. I want to write logic where few rows are rolled same No. Please let me know what is best way to solve this. I have used left outer join on same table but its giving me cross join.
NO ID
1 A
1 B
1 C
2 A
2 B
2 C
NO ID RoID
1 A C
1 B
2 A C
2 B
You could achieve your desired output using Analytic functions:
MAX() OVER()
LAG() OVER()
For example,
SQL> WITH sample_data AS(
2 SELECT 1 NO, 'A' ID FROM dual UNION ALL
3 SELECT 1 NO, 'B' ID FROM dual UNION ALL
4 SELECT 1 NO, 'C' ID FROM dual UNION ALL
5 SELECT 2 NO, 'A' ID FROM dual UNION ALL
6 SELECT 2 NO, 'B' ID FROM dual UNION ALL
7 SELECT 2 NO, 'C' ID FROM dual
8 )
9 -- end of sample_data mocking a real table
10 SELECT no,
11 id,
12 lag(rn) over(PARTITION BY NO ORDER BY ID DESC) rn
13 FROM
14 ( SELECT t.*, MAX(ID) OVER(PARTITION BY NO ORDER BY ID DESC) rn FROM sample_data t
15 )
16 WHERE ID <> rn
17 ORDER BY no,
18 id;
NO I R
---------- - -
1 A C
1 B
2 A C
2 B

Get next row value based on returned list of rows

In Oracle, suppose I have a query that returns the following list:
ID Sequence#
12 1
15 3
25 5
All I know in this case is the ID of some row (let's suppose 12), I need to return the ID of a row with the next sequence number which in this case is 3 (id = 15)
How can I do it? I know there's a Oracle function lead, but I wasn't able to successfully impement is.
Yes, you can use lead function to get the next value. Here is an example of how it can be done.
-- sample of data from your question
SQL> with t1(ID, Sequence#) as
2 (
3 select 12, 1 from dual union all
4 select 15, 3 from dual union all
5 select 25, 5 from dual
6 )
7 select *
8 from (select id
9 , sequence#
10 , lead(sequence#) over(order by id) next_sequence#
11 , lead(id) over(order by id) next_id#
12 from t1
13 )
14 where id = 12
15 ;
ID SEQUENCE# NEXT_SEQUENCE# NEXT_ID#
---------- ---------- -------------- ----------
12 1 3 15
SELECT * FROM table1 where ID in (SELECT min(ID) FROM table1 WHERE ID > 12)
Select sequence from my_ table where id=(select min(id) from my_table where sequence> 1)
Replace (1) in the above query with any value that you are searching for its next