Using Row_Number to deal with non unique data - sql

I have 4 columns a,b,c,d.
Some of my rows have the same values for all columns, is there any option to use row_number to insert same row number for those rows and continue counting if at least one of the values is different from values in the previous row
Example:
a b c d
1 1 1 1
1 1 1 1
1 1 1 2
1 1 1 2
1 1 1 3
1 1 1 3
1 1 2 4
I need it to look like: r=row_number
r a b c d
1 1 1 1 1
1 1 1 1 1
2 1 1 1 2
2 1 1 1 2
3 1 1 1 3
3 1 1 1 3
4 1 1 2 4
P.S. How to write here something like a table?

declare #t table(a int, b int, c int, d int)
insert #t values(1,1,1,1),(1,1,1,1),(1,1,1,2),
(1,1,1,2),(1,1,1,3),(1,1,1,3),(1,1,1,4)
select dense_rank() over(order by a,b,c,d) r, a,b,c,d from #t
Result:
r a b c d
1 1 1 1 1
1 1 1 1 1
2 1 1 1 2
2 1 1 1 2
3 1 1 1 3
3 1 1 1 3
4 1 1 1 4

Related

Unable to use LAG function

I need to update a table as :
ID | START_DATE | response| FINAL_TREND
1 14-10-2021 4
1 15-10-2021 3
1 16-10-2021 2
1 17-10-2021 2
1 18-10-2021 3
1 19-10-2021 2
OUTPUT AS:
ID | START_DATE | response| FINAL_TREND
1 14-10-2021 4 NULL
1 15-10-2021 3 4
1 16-10-2021 2 3
1 17-10-2021 2 2
1 18-10-2021 3 2
1 19-10-2021 2 3
So, when running a code:
SELECT LAG(RESPONSE,1) OVER (ORDER BY START_DATE) AS NEW
FROM DUMMY_YC
Output as:
NULL
4
3
2
3
2
2
But when using same code in update AS:
UPDATE DUMMY_YC A SET A.RESPONSE = (SELECT LAG(B.RESPONSE,1) OVER (ORDER BY B.START_DATE) AS NEW
FROM DUMMY_YC B WHERE B.START_DATE=A.START_DATE)
output as:
7 rows updated.
But the actual updated value is
RESPONSE|
(null)
(null)
(null)
(null)
(null)
(null)
(null)
Helps will be appreciated. Working On Oracle SQL Developer.
I'd go with merge.
Before:
SQL> SELECT *
2 FROM test
3 ORDER BY id, start_date;
ID START_DATE RESPONSE FINAL_TREND
---------- ---------- ---------- -----------
1 14.10.2021 4 0
1 15.10.2021 3 0
1 16.10.2021 2 0
1 17.10.2021 2 0
1 18.10.2021 3 0
1 19.10.2021 2 0
6 rows selected.
Merge:
SQL> MERGE INTO test a
2 USING (SELECT b.id,
3 b.start_date,
4 b.response,
5 LAG (b.response, 1) OVER (ORDER BY b.start_date) AS final_trend
6 FROM test b) x
7 ON ( x.id = a.id
8 AND x.start_date = a.start_date)
9 WHEN MATCHED
10 THEN
11 UPDATE SET a.final_trend = x.final_trend;
6 rows merged.
After:
SQL> SELECT *
2 FROM test
3 ORDER BY id, start_date;
ID START_DATE RESPONSE FINAL_TREND
---------- ---------- ---------- -----------
1 14.10.2021 4
1 15.10.2021 3 4
1 16.10.2021 2 3
1 17.10.2021 2 2
1 18.10.2021 3 2
1 19.10.2021 2 3
6 rows selected.
SQL>

case when... for subgroups

I have table like this:
receipt
position
unit
booking time
1
1
1
08:00:00
1
2
1
08:00:05
1
3
1
08:00:11
1
4
1
08:00:18
1
5
1
08:00:21
1
6
5
08:00:25
1
1
1
08:00:30
1
2
1
08:00:33
1
3
1
08:00:37
1
4
1
08:00:40
1
5
1
08:00:49
2
1
1
08:01:55
2
2
1
08:01:58
2
3
1
08:02:04
3
1
1
08:02:20
3
2
5
08:02:24
3
1
1
08:02:30
3
2
1
08:02:35
I want to check for every receipt whether unit 5 exists or not. If unit 5 exists, I only want to select positions with a booking time after the entry with unit 5.
For the example above my result therefore should look like this:
receipt
position
unit
bookingtime
1
1
1
08:00:30
1
2
1
08:00:33
1
3
1
08:00:37
1
4
1
08:00:40
1
5
1
08:00:49
2
1
1
08:01:55
2
2
1
08:01:58
2
3
1
08:02:04
3
1
1
08:02:30
3
2
1
08:02:35
I have kind of a start, which delivers the right result if there was only one receipt:
Select * from test
where bookingtime> (case
when (select Max(bookingtime) from test where unit=5) is null
then (Select convert(time,'00:00:00'))
Else (select Max(bookingtime) from testdb where unit=5)
End)
What am I missing to let this code run through every single receipt separately so that I get the result I am looking for?
You can use a window function to get the time for unit 5:
select t.*
from (select t.*,
min(case when unit = 5 then bookingtime end) over (partition by receipt) as bookingtime_5
from t
) t
where bookingtime_5 is null or
bookingtime > bookingtime_5;

Sequence in SELECT statement

I need to create SELECT statement with sequence in Oracle. When col_flag is 1 then sequence increase with mod(col_seq, max_seq) and when col_flag is 0 then sequence don't increment.
Example:
col_group col_flag col_seq
--------- -------- --------
A 1 1
A 1 2
A 1 3
A 0 3
A 0 3
B 1 4
B 1 1
B 1 2
B 1 3
B 0 3
B 1 4
B 1 1
C 1 2
C 0 2
...
It guess that a window sum and arithmetics can do what you want - but you need a column that defines the ordering of the rows, I assumed id.
select col_flag,
mod(sum(col_flag) over(order by id), 4) + 1 col_seq
from mybltae

How to Subtotal Value with MAX

1.I have data as follows (just a subset - there are 20K records)
sku,id
1 1
1 2
1 2
1 2
1 3
1 4
1 1
1 2
1 3
1 4
1 4
1 4
1 5
1 6
1 6
2 1
2 1
2 2
2 3
2 3
2 3
2 4
2 4
2 5
2 5
2 6
2 7
2 1
2 2
2 3
The above values translate to
1 = 4 records
1 = 6 records
2 = 7 records
2 = 3 records
The MAX would just give me 6 for one and 7 for 2
The actual total is 1 = 10 and 2 = 10
How do I sum up to get the correct values?
You can use order by and some way of limiting rows. In standard SQL this would be:
select t.*
from t
order by id desc
fetch first 2 rows only;
However, some databases might use limit or select top or some other method.
No handling of ties here. Thousands of other questions handle this topic.
select sku, id
from (
select *, row_number() over (order by id desc) rn
from T
) t
where rn <= 2
order by rn desc;

MySQL SUM Query

I've got two tables.
I'm trying to calculating the SUM quantity of tbl1
tbl1.xid is the primary, while tbl2.xid is the foreign
tbl1
xid pub quantity
1 1 10
2 1 2
3 0 1
4 1 5
tbl2
id ttype fno xid qnty
1 A 0 1 0
2 A 1 1 3
3 B 1 1 4
4 A 1 2 1
5 A 1 3 2
6 A 1 4 3
7 A 1 4 1
8 A 0 1 0
We are calculating the sum of tbl1's quantity
1) Whos tbl1.pub is 1
Thus tbl1.xid 3 is removed form the list, for it's pub is 0
Results
tbl1
xid pub quantity
1 1 10
2 1 2
4 1 5
2) AND Who's tbl1 has at least one tbl2.xid who's tbl2.ttype is 'A' and who's tbl2.fno is '0'
Thus tbl1.xid 2 & 4 are removed form the list, because none of them have at least one tbl2.xid who's fno is '0' and who's tbl2.ttype is 'A'
Results
parent_tbl1
xid pub quantity
1 1 10
The final results should be 10
SELECT SUM(quantity) AS Total
FROM tbl1
WHERE pub=1
AND EXISTS
(SELECT *
FROM tbl2
WHERE tbl2.ttype = 'A'
AND tbl2.fno = 0
AND tbl1.xid = tbl2.xid
)