Getting the first occurrence of group of rows - oracle

Am having a case where I have transaction and this transaction consists of several steps. I want to return the first occurrence of this transaction, for example:
Trn Loc step
111 0 1
111 0 2
111 0 3
222 3 1
222 3 2
333 5 1
333 5 2
333 5 3
and i want to get this result :
tran loc
111 0
222 3
333 5
I think it is supposed to be done by partition function but I don't know how...any help please?

select t.trn, t.loc
from (select trn, loc, ROW_NUMBER() OVER (PARTITION BY trn, loc ORDER BY trn, loc) as rnum
from table ) t
where t.rnum = 1
Or you can use RANK() function instead of ROW_NUMBER(), rest of syntax is same.
http://www.techonthenet.com/oracle/functions/rank.php

Related

Google sheet query 2 columns as search key and search

I met some problem with google sheet function.
I have 2 tables. I want to search table1 Date+User as key value in table2.
example:
Date User Unit
2022/05/30 A 109
2022/05/30 B 119
2022/05/30 C 119
2022/05/29 D 109
2022/05/29 E 114
Date User Amount
2022/05/30 A 1
2022/05/30 B 2
2022/05/30 C 3
2022/05/30 D 41
2022/05/30 E 5
2022/05/29 D 6
2022/05/29 E 7
2022/05/29 F 81
2022/05/29 G 9
2022/05/29 A 101
2022/05/29 B 11
2022/05/29 C 121
2022/05/29 D 13
after query I hope the table looks like
Hope Result
Date User Unit Amount
2022/05/30 A 109 1
2022/05/30 B 119 2
2022/05/30 C 119 3
2022/05/29 D 109 6
2022/05/29 E 114 7
This is a sample google sheet
https://docs.google.com/spreadsheets/d/1oxhWMVPt-GziG10agob-xbiNYfKrZVFK9ro0Pj7tn6Y/edit#gid=0
Can I ask for help ?
Many Thanks
Two options. The first pulls all matching combinations of DATE and USER
=ARRAYFORMULA(
QUERY(
{E2:G,
IF(ISBLANK(E2:E),,
IFERROR(
VLOOKUP(
E2:E&"|"&F2:F,
{A2:A&"|"&B2:B,C2:C},
2,FALSE)))},
"select Col1, Col2, Col4, Col3
where Col4 is not null
label
Col1 'Date',
Col2 'User',
Col3 'Amount',
Col4 'Unit'"))
which returns
Date
User
Unit
Amount
2022/05/30
A
109
1
2022/05/30
B
119
2
2022/05/30
C
119
3
2022/05/29
D
109
6
2022/05/29
E
114
7
2022/05/29
D
109
13
The second matches your output exactly, but does omit that second D value for the 29th (13)
=ARRAYFORMULA(
QUERY(
{IFERROR(
VLOOKUP(
UNIQUE(E2:E&"|"&F2:F),
{E2:E&"|"&F2:F,E2:G},
{2,3,4},FALSE)),
IFERROR(
VLOOKUP(
UNIQUE(E2:E&"|"&F2:F),
{A2:A&"|"&B2:B,C2:C},
2,FALSE))},
"where Col4 is not null
format Col1 'yyyy/mm/dd'"))
Both have been added to your sheet. If either of these work out for you, I can break it down.

Retrieve the list of data from database using hibernate criteria

I have a table called employee_comp_field, where salary fields are available
comp_field id | year_id | compensation_field
1 101 salary
2 101 bonus
3 101 pf
4 101 allowance
5 102 salary
6 102 bonus
7 102 pf
8 102 allowance
Then I have another table where employee salary data get stored emp_compensation against each field. As you can see emp_id 10 has three set of records as he got three time salary hike in the same year(year_id=101), which can be identified by salary_order field.
id | year_id | emp_id | comp_field_id | amount | comp_order
1 101 10 1 10000 1
2 101 10 2 1000 1
3 101 10 3 1000 1
4 101 10 4 100 1
5 101 10 1 12000 2
6 101 10 2 100 2
7 101 10 3 10000 2
8 101 10 4 10000 2
9 101 10 1 15000 3
10 101 10 2 500 3
11 101 10 3 150 3
12 101 10 4 1500 3
13 101 11 1 13000 1
14 101 11 2 1300 1
15 101 11 3 null 1
16 101 11 4 150 1
I want to identify all the employees list with max salary_order
my desire output will be below:
id | year_id | emp_id | comp_field_id | amount | comp_order
9 101 10 1 15000 3
10 101 10 2 500 3
11 101 10 3 150 3
12 101 10 4 1500 3
13 101 11 1 13000 1
14 101 11 2 1300 1
15 101 11 3 null 1
16 101 11 4 150 1
as emp_id 10 got three time salary hike...so I retrieve the list of records with salary_order 3
and emp_id 11 got one ony so I retrieve that set of records ony with salary_order 1
Can someone please help me here, how to retrieve my desire output using hibernate criteria.
My thought is to first retrieve all the list based on emp_id and then using java stream if we can filter it out to get the desired output.
Please suggest the best possible way.
The best possible way.
is subjective. It can be the fastest, it can be the shortest. It could be anything.
I will give you an example of how you could build a query in mysql to replicate your output. This might be tricky to solve with Criteria though since the table is being self joined.
select a.*
from emp_compensation a
left outer join emp_compensation b on a.emp_id = b.emp_id
and a.comp_field_id = b.comp_field_id
and a.comp_order < b.comp_order
where b.emp_id is null

Each row 3 column sum result show as running total in last column, then from 2nd row > first row running total show in first column with group by

Each row Total value go for the set OP value for the next row, except the first row
My Table Data
Id
WarehouseId
ProductId
OP
RE
IS
Total
1
100
10000
10
0
0
10
2
100
10000
0
0
5
5
4
100
10000
0
15
0
15
5
101
10001
15
0
0
15
6
101
10001
0
0
5
5
8
101
10001
0
15
0
15
9
101
10002
25
0
0
25
10
101
10002
0
0
10
10
11
101
10002
0
15
0
15
I want to show below result (OP+RE)-IS=Total
Id
WarehouseId
ProductId
OP
RE
IS
Total
1
100
10000
10
0
0
10
2
100
10000
10
0
5
5
4
100
10000
5
15
0
20
5
101
10001
15
0
0
15
6
101
10001
15
0
5
10
8
101
10001
10
15
0
25
9
101
10002
25
0
0
25
10
101
10002
25
0
10
15
11
101
10002
15
15
0
30
You can use recursive subquery factoring for that purpose like below. You need to rank your data as you have some gaps between IDs in your data. Column name = IS is not allowed, You should use "IS" enclosed by ".
with t1 ( ID, WAREHOUSEID, PRODUCTID, OP, RE, "IS", RNB, rnb_per_wh_prod) as (
select ID, WAREHOUSEID, PRODUCTID, OP, RE, "IS"
, row_number()over(order by WAREHOUSEID, PRODUCTID, ID) rnb
, row_number()over(partition by WAREHOUSEID, PRODUCTID order by ID) rnb_per_wh_prod
from Your_table t
), cte (ID, WAREHOUSEID, PRODUCTID, OP, RE, "IS", Total, RNB) as (
select ID, WAREHOUSEID, PRODUCTID, OP, RE, "IS", OP + RE - "IS", RNB
from t1
where rnb_per_wh_prod = 1
union all
select t1.ID
, t1.WAREHOUSEID
, t1.PRODUCTID
, case when t1.op = 0 then c.OP + c.RE - c."IS" else t1.OP end as OP
, t1.RE
, t1."IS"
, case when t1.op = 0 then c.OP + c.RE - c."IS" else t1.OP end + t1.RE - t1."IS" total
, t1.RNB
from cte c
join t1 on (t1.RNB = c.RNB + 1
and c.WAREHOUSEID = t1.WAREHOUSEID
and c.PRODUCTID = t1.PRODUCTID)
)
select ID, WAREHOUSEID, PRODUCTID, OP, RE, "IS", TOTAL
from cte
order by id
;
If I understand the problem correctly, "every 3 row" is a coincidence in your data; in fact, the computation must be done separately for each product in each warehouse, no matter how many rows there are for each distinct combination. And the "id" column is in reality some sort of timestamp - ordering is by "id".
If so, you can do it all in a single query using analytic sum(). Instead of creating a table for testing, I included all the sample data in a WITH clause at the top of the query itself; you can remove the WITH clause, and use your actual table and column names. I also changed the column name is to is_ since is is a reserved keyword, it can't be a column name.
Note also that I am ignoring your existing total column completely (I didn't even include it in the sample data); I assume it doesn't exist in your real-life data, and instead it is part of your attempt at a solution. You don't need it - not in the way you have it in your question.
with
sample_data (id, warehouseid, productid, op, re, is_) as (
select 1, 100, 10000, 10, 0, 0 from dual union all
select 2, 100, 10000, 0, 0, 5 from dual union all
select 4, 100, 10000, 0, 15, 0 from dual union all
select 5, 101, 10001, 15, 0, 0 from dual union all
select 6, 101, 10001, 0, 0, 5 from dual union all
select 8, 101, 10001, 0, 15, 0 from dual union all
select 9, 101, 10002, 25, 0, 0 from dual union all
select 10, 101, 10002, 0, 0, 10 from dual union all
select 11, 101, 10002, 0, 15, 0 from dual
)
select id, warehouseid, productid,
nvl(sum(op + re - is_) over (partition by warehouseid, productid
order by id rows between unbounded preceding and 1 preceding),
op) as op,
re, is_,
sum(op + re - is_) over
(partition by warehouseid, productid order by id) as total
from sample_data
;
ID WAREHOUSEID PRODUCTID OP RE IS_ TOTAL
------ ----------- ---------- ---------- ---------- ---------- ----------
1 100 10000 10 0 0 10
2 100 10000 10 0 5 5
4 100 10000 5 15 0 20
5 101 10001 15 0 0 15
6 101 10001 15 0 5 10
8 101 10001 10 15 0 25
9 101 10002 25 0 0 25
10 101 10002 25 0 10 15
11 101 10002 15 15 0 30

Expresiones Regulares Oracle 11g

I have a problem I want to compare values ​​from Column A that exist in Column B, regardless of the order they are in Column B
Ex:
Column A 177 Column B 177
Column A 2 : 3 : 1 : 18 : 123 : 170 Column B 18 : 123 : 3 : 2 : 3 : 1 : 1
Column A 2 : 3 : 177 : 123 Column B 3 : 123 : 2 : 177
Column A 2 : 3 : 1 : 123 : 177 Column B 1 : 123 : 2 : 3 : 3 : 1
Column A 172 Column B 1
Column A 2 : 3 : 1 : 18 : 123 : 177 Column B 3 : 1 : 18 : 123 : 3 : 2 : 1
We can see that the first record OK
second record, NO, since the value 170 does not exist
third registration, OK, although the order is not the same as column A, but there are values
fourth record, No
Fifth record, No
Sixth Registor No
Thank you very much for the help friends!
I'm using Oragle 11g.
You are trying to achieve string to table functionality in SQL.
As explained here, the below snippet would be a good start. You can extend the below by changing the delimiter to : instead of , and then include DENSE RANK to compare the column values within the group. Once you break the string into multiple rows then you can easily compare. So instead of a direct check like C1 = C2 you may include the DENSE RANK values to nail this.
I don't have access to any Oracle instance for a fiddle or test and even sqlfiddle.com is broken for ages now. But this pointer should help you in some way. The link I have included contains multiple choices for this functionality.
SQL> SELECT str
2 , REGEXP_SUBSTR(str, '[^,]+', 1, LEVEL) AS single_element
3 , LEVEL AS element_no
4 FROM (
5 SELECT ROWNUM AS id
6 , str
7 FROM t
8 )
9 CONNECT BY INSTR(str, ',', 1, LEVEL-1) > 0
10 AND id = PRIOR id
11 AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL;
STR SINGLE_ELEMENT ELEMENT_NO
------------------------------ ------------------------------ ----------
X,Y,Z X 1
X,Y,Z Y 2
X,Y,Z Z 3
XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG XXX 1
XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG Y 2
XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG ZZ 3
XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG AAAAA 4
XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG B 5
XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG CCC 6
XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG D 7
XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG E 8
XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG F 9
XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG GGG 10

Decreasing running total in oracle sql

Table A
Week Column_1 Column_2
0 9 92
1 0 84
2 1 84
3 4 83
The result I want is
Week Column_1 Column_2 Remaining
0 9 92 83
1 0 84 83
2 1 84 82
3 4 83 78
So, if you notice. I want to calculate the Remaining as Column_2 - Column_1 for week 0 and after week 0 I want to calculate the Remaining as Remaining - Column_1
Is it possible?
You can use this query.
SELECT a.*,
SUM (CASE
WHEN a.week = 0 THEN column_2 - column_1
ELSE -column_1
END)
over (
ORDER BY week )
FROM tablea a;

Resources