How do I compare rows in an Oracle Table? - oracle

I have a table that's like this
rank continuationofrow
1 row
2 row
3 row
4 row
4 row
4 row
I'm trying to identify the previous rows rank number within an Oracle statement. Any help is greatly appreciated. I've searched the internet and haven't found much.

You must have another column that establishes the order of the rows with the same rank, otherwise the concept of "previous row" is meaningless. Let's suppose you do:
seq rank continuationofrow
1 1 row
2 2 row
3 3 row
4 4 row
5 4 row
6 4 row
No you can use an analytic function:
select seq, rank, continuationofrow, lag(rank) over (order by seq) as prev_rank
from mytable;
seq rank continuationofrow prev_rank
1 1 row
2 2 row 1
3 3 row 2
4 4 row 3
5 4 row 4
6 4 row 4

select
...
lag(rank, 1) over (order by ordering-columns)
from
..

Related

Why when using grouping_id with rollup the total will be level 3 instead of 2?

Is there any logic behind the reason to why the total grouping when using rollup will be "lvl" 3?..
example:
col1
col2
id1
1
id1
2
id2
1
id2
2
id3
1
id3
2
In cube method this is understandable as
level 0 is the "basic values" (my own term)such as "col1-ID1","col2-id1", "col3-id1" etc..,
level 1 will be the subtotal row of each basic value which means subtotal of ID1(1)+ID1(2) --> id1(3) for example.
level 2 will be the total of each combination which means subtotal of 1's and subtotal of 2's , in this example: 1- subtotal will be 3 and 2-subtotal will be 6
and level 3 will be the grand total of them all, in this example: 9
my explanation might not make any sense:) .. sorry
Is there any reason behind that skipping from lvl 0/1 straight to 3? or its just the way it is?
Summary: The grand total will be in the grouping set with the id the maximum value of the grouping set which is equal to 2(number of columns in the grouping set) - 1. Therefore, with 2 columns being cubed, the grand total is in 22-1 = 3 and, with 3 columns being cubed, the grand total is in 23-1 = 7.
Given the query:
SELECT LISTAGG(col1, ',') WITHIN GROUP (ORDER BY col1) AS col1,
LISTAGG(col2, ',') WITHIN GROUP (ORDER BY col2) AS col2,
GROUPING_ID(col1, col2) AS grp
FROM table_name
GROUP BY CUBE(col1, col2)
ORDER BY grp, col1, col2
Which, for the sample data:
CREATE TABLE table_name (col1, col2) AS
SELECT 'id1', 1 FROM DUAL UNION ALL
SELECT 'id1', 2 FROM DUAL UNION ALL
SELECT 'id2', 1 FROM DUAL UNION ALL
SELECT 'id2', 2 FROM DUAL UNION ALL
SELECT 'id3', 1 FROM DUAL UNION ALL
SELECT 'id3', 2 FROM DUAL;
Outputs:
COL1
COL2
GRP
id1
1
0
id1
2
0
id2
1
0
id2
2
0
id3
1
0
id3
2
0
id1,id1
1,2
1
id2,id2
1,2
1
id3,id3
1,2
1
id1,id2,id3
1,1,1
2
id1,id2,id3
2,2,2
2
id1,id1,id2,id2,id3,id3
1,1,1,2,2,2
3
You can see that when GROUPING_ID(col1, col2) is:
The un-grouped value.
The value grouped by the first column in the grouping set (and there is one value for the first column and N values for the second column).
The value grouped by the second column in the grouping set (and there are M values for the first column and one value for the second column).
The value grouped by the both columns in the grouping set (and there are M values for the first column and N values for the second column giving N*M total values); which will give you the grand total.
If you had the sample data with 3 columns:
CREATE TABLE table2 (col1, col2, col3) AS
SELECT t1.COLUMN_VALUE,
t2.COLUMN_VALUE,
t3.COLUMN_VALUE
FROM TABLE(SYS.ODCIVARCHAR2LIST('id1', 'id2', 'id3')) t1
CROSS JOIN TABLE(SYS.ODCINUMBERLIST(1, 2)) t2
CROSS JOIN TABLE(SYS.ODCINUMBERLIST(3, 4)) t3;
Then using CUBE across 3 columns:
SELECT LISTAGG(col1, ',') WITHIN GROUP (ORDER BY col1) AS col1,
LISTAGG(col2, ',') WITHIN GROUP (ORDER BY col2) AS col2,
LISTAGG(col3, ',') WITHIN GROUP (ORDER BY col3) AS col3,
GROUPING_ID(col1, col2, col3) AS grp
FROM table2
GROUP BY CUBE(col1, col2, col3)
ORDER BY grp, col1, col2, col3
Outputs:
COL1
COL2
COL3
GRP
id1
1
3
0
id1
1
4
0
id1
2
3
0
id1
2
4
0
id2
1
3
0
id2
1
4
0
id2
2
3
0
id2
2
4
0
id3
1
3
0
id3
1
4
0
id3
2
3
0
id3
2
4
0
id1,id1
1,1
3,4
1
id1,id1
2,2
3,4
1
id2,id2
1,1
3,4
1
id2,id2
2,2
3,4
1
id3,id3
1,1
3,4
1
id3,id3
2,2
3,4
1
id1,id1
1,2
3,3
2
id1,id1
1,2
4,4
2
id2,id2
1,2
3,3
2
id2,id2
1,2
4,4
2
id3,id3
1,2
3,3
2
id3,id3
1,2
4,4
2
id1,id1,id1,id1
1,1,2,2
3,3,4,4
3
id2,id2,id2,id2
1,1,2,2
3,3,4,4
3
id3,id3,id3,id3
1,1,2,2
3,3,4,4
3
id1,id2,id3
1,1,1
3,3,3
4
id1,id2,id3
1,1,1
4,4,4
4
id1,id2,id3
2,2,2
3,3,3
4
id1,id2,id3
2,2,2
4,4,4
4
id1,id1,id2,id2,id3,id3
1,1,1,1,1,1
3,3,3,4,4,4
5
id1,id1,id2,id2,id3,id3
2,2,2,2,2,2
3,3,3,4,4,4
5
id1,id1,id2,id2,id3,id3
1,1,1,2,2,2
3,3,3,3,3,3
6
id1,id1,id2,id2,id3,id3
1,1,1,2,2,2
4,4,4,4,4,4
6
id1,id1,id1,id1,id2,id2,id2,id2,id3,id3,id3,id3
1,1,1,1,1,1,2,2,2,2,2,2
3,3,3,3,3,3,4,4,4,4,4,4
7
And will generate 23 = 8 levels (from 0 to 7) since there are all the possible combinations of grouping 3 columns and the grand-total will be in level 7; compared to 22 levels (0 to 3) when you are cubing 2 columns and the grand total is in level 3.
fiddle
Update
What I don't understand is why roll up is skipping level 2 straight to 3?
From the SELECT documentation:
ROLLUP
The ROLLUP operation in the simple_grouping_clause groups the selected rows based on the values of the first n, n-1, n-2, ... 0 expressions in the GROUP BY specification, and returns a single row of summary for each group.
[...]
CUBE
The CUBE operation in the simple_grouping_clause groups the selected rows based on the values of all possible combinations of expressions in the specification. It returns a single row of summary information for each group.
CUBE generates all possible grouping sets; ROLLUP generates groups of the first 1 column then with the first 2 columns, 3 columns, ..., up to n columns which is the same as the CUBE when the grouping sets are restricted to the 20-1, 21-1, 22-1, ..., 2n-1 (or more simply 0, 1, 3, 7, ... 2n-1).
This means that ROLLUP will skip the grouping set with id 2 as that is grouping only by the 2nd column and that is not "one of the first n, n-1, n-2, ... 0 expressions" in the GROUP BY specification.
fiddle

Swapping the duplicates in Column

I need some help to determine the best approach on how I can use VBA to find duplicates in a column 2 and swap the rows that have the duplicates in Column 2 (in this example the row 5 with row 6). Please see below sample.
Column 1 Column 2 Column 3
A 1 yes
B 2 no
C 3 no
D 4 yes
E 5 no
F 5 yes

DAX measure: disctinct count per group

Excel - Power Pivot
I am trying to create a measure to calculate a disctinct count (or a sum of a disctinct count) of a column - grouped by a second column.
Based on the column "lot" an the column "sku", I want to calculate the column "count_distinct_sku_by_lot". Column "sqm" is not relevant.
Which DAX code I could use?
(picture of data added)
lot sku sqm count_distinct_sku_by_lot
lot1 sku1 1 1
lot2 sku2 2 2
lot2 sku2 3 2
lot2 sku3 4 2
lot3 sku4 5 3
lot3 sku4 6 3
lot3 sku5 7 3
lot3 sku5 8 3
lot3 sku6 9 3
lot4 sku7 11 1
You can create a calculated Column :
DistinctCount =
VAR VrCurrentRow = [lot]
RETURN
CALCULATE(
DISTINCTCOUNT(Sheet1[sku]);
FILTER(
Sheet1;
Sheet1[lot] = VrCurrentRow
)
)
Result :

In Oracle, repeatedly assign values from a set to column

I have a table in Oracle that has a column that I would like to assign a value to from a set of possible values. I like to assign the values in order of the set, repeatedly, for the entire table.
For example:
If the set of values is {1, 2, 3}. I'd like to assign the values in this pattern until the last row is reached:
rowNum someCol valueCol
1 this 1
2 is 2
3 some 3
4 other 1
5 column 2
6 in 3
7 the 1
8 table 2
I can't figure out how to do this with a traditional update statement. Anone that could help with this problem?
Use Modulo to achieve desire result
UPDATE TableName
SET valueCol= CASE WHEN rowNum % 3 == 1 then 1
WHEN rowNum % 3 == 2 then 2
WHEN rowNum % 3 == 0 then 3
END
update tablename
set valuecol = case mod(rownum, 3) when 0 then 3 else mod(rownum, 3) end
;

PL/SQL Oracle 11g Looping

I am having trouble solve. I am suppose to be getting a record every time there is a change to an account in our data warehouse, but I am only receiving one. The table below is a sample of what I am working with.
Row Acct1 Acct2 Date Total_Reissued Reissue_Per_Day
1 A 1 1/1/2016 2 2
2 A 1 1/2/2016 3 1
3 A 1 1/3/2016 5 2
4 A 1 1/4/2016 6 1
1 B 3 1/1/2016 1 1
2 B 3 1/2/2016 2 1
1 B 4 1/1/2016 1 1
2 B 4 1/2/2016 2 1
The Reissued Column is a running total. For Acct A on 1/1/2016 there were 2 reissues, then On 1/2/2016 there was 1 more making a total of 3. My problem is calculating the actual number of reissues per day.
You can use the lag() function to peek back at the previous row; assuming that 'previous' is the last date you saw for the acct1/acct2 combination you can do:
select row_number() over (partition by acct1, acct2 order by dt) as row_num,
acct1, acct2, dt, total_reissued,
total_reissued - nvl(lag(total_reissued)
over (partition by acct1, acct2 order by dt), 0) as reissue_per_day
from your_table;
ROW_NUM A ACCT2 DT TOTAL_REISSUED REISSUE_PER_DAY
---------- - ---------- ---------- -------------- ---------------
1 A 1 2016-01-01 2 2
2 A 1 2016-01-02 3 1
3 A 1 2016-01-03 5 2
4 A 1 2016-01-04 6 1
1 B 3 2016-01-01 1 1
2 B 3 2016-01-02 2 1
1 B 4 2016-01-01 1 1
2 B 4 2016-01-02 2 1
I'm not sure if your 'row' column actually exists, or is required, or was just to illustrate your data. I've generated it anyway, in case you need it.
The main bit of interest is:
lag(total_reissued) over (partition by acct1, acct2 order by dt)
which finds the previous date's value (using dt as a column name, since date isn't a valid name). That then has an nvl() wrapper so the first row sees a dummy value of zero instead of null. And then that is subtracted from the current row's value to get the difference.

Resources