Deleting opposite duplicates in Oracle SQL - oracle

I have some issues that I hope you can lend a helping hand towards.
So I have some data with opposite value, for example:
Amount Type ID
10000 10 25
-10000 10 25
20000 11 30
30000 12 49
-30000 12 49
Sorry for the ugly table.
But how can I delete the lines where the amount cancelled out? I would like the ones with 10000 and -10000 to be deleted. But I wont know the specific type and id number. (30000 and -30000 is the same issue).
Any ideas? I've been searching forever, but can only find how to remove a duplicate row, and not both rows.
Hope it makes sense :)
Update. Thanks for the solutions so far! :)
There can be more than 1:1 in the amount column, but those wouldn't identical Type and ID. For exampel could a 6th entry look like this:
Amount Type ID
10000 10 25
-10000 10 25
20000 11 30
30000 12 49
-30000 12 49
10000 31 42
And the last one should not be deleted :) Hope it makes sense now.

On the basis only of the limited information provided...
DELETE x
FROM my_table x
JOIN my_table y
ON y.id = x.id
AND y.type = x.type
AND y.amount = x.amount * -1;

Related

Index column not resetting after I apply filter in Dax?

I have table which shows time difference between different types of ID's for when an alert is given. The time since prev will say when the next alert is on the device ID.
my table looks like this:
Time Device ID Type TimeSincePrev(seconds) index
22.1.21 04:02:04 12 None 0 1
22.1.21 04:24:07 13 low 1320 2
22.1.21 04:26:04 14 medium 120 3
......
...
......
...
...
However When I filter by deviceID, the indexes will not reset to 1,2,3...., instead, it will go to a random number, causing the timesinceprev alert to be wrong. How do I correct so that index is correct, hopefully correcting the TimeSincePrev column. Also if there is a way to get TimeSincePrev to show seconds via the the seconds and not just via the minute like it is now
This is what the query for the index column looks like:
index= COUNTROWS(FILTER(VALUES('Table'[Time]),
'Table'[Time]<EARLIER('Table'[Time])
))+1
Here is how TimeSincePrev:
TimeSincePrev= IF(DATEDIFF(LOOKUPVALUE('Table'[Time],'Table'[index],
'Table'[index]-1),MINUTE)>720,BLANK(),DATEDIFF(LOOKUPVALUE('Table'[Time],
'Table'[index],'Table'[index]-1),'Table'[Time],MINUTE))*60
How do I get it so when I filter by device ID the indexes don't mess up like this:
Time Device ID Type TimeSincePrev(seconds) index
22.1.21 04:02:04 12 None 0 6
22.1.21 04:24:07 12 low 1320 3
22.1.21 04:26:04 12 medium 120 1
22.1.21 04:02:04 12 None 0 2
22.1.21 04:24:07 12 low 1320 4
22.1.21 04:26:04 12 medium 120 5
......
...
......
...
...
Are you using a column for this? If so, you need to create a measure that handles the indexing instead.
Columns are re-calculated only at refresh time (when you refresh the dataset), NOT at query time (when you click on slicers). The column cannot respond to your selected slicer value and calculate on the fly.

Hive SELECT col, COUNT(*) mismatch

Let me start by saying, I am very new to Hive, so I'm not sure what information folks will need to help me out. Please let me know what information would be useful. Also, while I'd usually create a small dataset to recreate the problem with, I think this problem has to do with the scale of my dataset, because I can't seem to recreate the problem on a smaller dataset. Let me know if you have suggestions to make this more easy to answer.
Okay now that's out of the way, here's my problem. I have a huge dataset, partitioned by month, with about 500 million rows per month. I have a column with an ID number in it (I'll call it idcol), and I want to closely examine a couple of examples where there's a high number of repeated IDs and a very low number. So, I used this:
SELECT idcol, COUNT(*) FROM table WHERE month = 7 GROUP BY idcol LIMIT 10;
And got:
000005185884381 13
000035323848000 24
000017027256315 531
000010121767109 54
000039844553332 3
000013731352481 309
000024387407996 3
000028461234451 67
000016564844672 1
000032933040806 17
So, I went to investigate the first idvar with a count of 3, with:
SELECT * FROM table WHERE month = 7 AND idcol = '000039844553332';
I expected to see just 3 rows, but ended up with 469 rows found! That was strange enough, but then I just happened to run the original line of code above but with LIMIT 5 instead and ended up with:
000005185884381 13
000017027256315 75
000010121767109 25
000013731352481 59
000024387407996 1
And, it may be hard to see because the idcol is so long, but idvar 000017027256315 ended up with a count of 531 when I did LIMIT 10 and just 75 when I did LIMIT 5.
What am I missing?! How can I get a correct count of just a small number of values so I can investigate further?!
BTW my first thought was to make the counting part a sub-query, but that didn't change a thing. I used:
SELECT * FROM (SELECT idcol, COUNT(*) FROM table WHERE month = 7 GROUP BY idcol) x LIMIT 10;
...same EXACT results
Most likely the counts are being computed from statistics.See here for the bug and the related discussion.
hive.compute.query.using.stats = FALSE
If this doesn't fix it try the ANALYZE command before running the count(*)
ANALYZE TABLE table_name PARTITION(month) COMPUTE STATISTICS;

Transpose without PIVOT in ORACLE

currently I am using pl/sql Developer(Oracle). I am told to convert a Row wise arranged data into columns but without the use of PIVOT. Since the Table I am working on dynamically changes, I am not able to use DECODE too.
POLICY SEQS INVDATE SUM(AMT)
-------- ------ ----------- ----------
policA 123 01-JAN-10 40
policA 123 01-FEB-10 50
policA 123 01-MAR-10 60
policA 456 01-JAN-10 360
policA 456 01-FEB-10 450
policA 456 01-MAR-10 540
policA 789 01-FEB-10 1000
polcA 789 01-MAR-10 1000
I have to re-arrange the dates and the sum of amounts column wise. So that the Single Policy and Single SEQS will have the dates and its amount column wise in a line.
"POLICY","SEQS","INST1","INST1SUM","INST2","INST2SUM","INST3","INST3SUM"
"policA","123","01-JAN-10","40","01-FEB-10","50","01-MAR-10","60"
"policA","456","01-JAN-10","360","01-FEB-10","450","01-MAR-10","540"
"policA","789","01-FEB-10","1000","01-MAR-10","1000"
Some Policy might not be starting from Jan, so the INST1 must be from feb, INST2 must be Mar and INST3 and corresponding INSTSUM must be NULL.
Is there any way that this can be done using CROSS JOINS or using xml function?
Can I use xmlagg with alternative data (INST and SUM)?
I have done some research and am not able to solve this out. Can you please help me with this?

Sum Column At Each Value Change of another field in foxpro

Sum Column At Each Value Change of another field in foxpro. How can I get the additive column? I was able to do a running total but for all the items how can I get it to start at each item change?
E.g.
Item Number QTY ADDITIVE
1045 50 50
1045 25 75
1045 35 110
2045 50 50
2045 50 100
2045 25 125
3056 30 30
3056 30 60
3056 30 90
It looks like simple additive, but how are you planning on storing and presenting to the end-user the results... in a grid or just final running total per individual item? It looks like this might represent sales order item / qty sold. I would probably query into a read/write cursor ordered by item, then apply a scan loop to update each one... something like.
select ItemNumber, Qty, 000000 as RunningTotal ;
from YourTable ;
order by ItemNumber ;
into cursor C_Sample readwrite
lastItem = ""
runTotal = 0
scan
*/ If different item, reset running total back to zero
if lastItem != ItemNumber
runTotal = 0
endif
*/ Update running total
runTotal = runTotal + Qty
*/ Update the record column
replace RunningTotal with runTotal
*/ preserve the ID we just processed for comparison to next record
lastItem = ItemNumber
endscan
*/ Done...

SQL Oracle Sort string (numbers) and (letters with numbers)

I am new to oracle and I have a problem.
I have a column named file_id.
When I do an order by it sorts strings such as
1
1
10
100
11
11
110
114
12
300
31
4200
B14
B170
B18
edit:
I would like it to sort this way.
1
1
10
11
11
12
31
100
300
4200
B14
B18
B170
The answer below works perfectly. Only other problem I ran into now..I have records that are blank. How could I make the blank records order at the end?
1
1
10
11
11
12
31
100
300
4200
BLANK
BLANK
BLANK
BLANK
BLANK
B14
B18
B170
Thank you for your help.
select column
from table
order by
regexp_substr(column, '^\D*') nulls first,
to_number(regexp_substr(column, '\d+'))
fiddle
This is an old question, but it was the first hit on google so I thought I'd share an alternative solution:
select column
from table
order by
LPAD(column, 10)
The LPAD function pads the left-side of the string with spaces so that the results will be sorted numerically. This works for non-numeric values, and null values will be sorted last. This works well if you know the maximum length of the strings to be sorted (you may need to adjust the second parameter to suit your needs).
Source: http://www.techonthenet.com/oracle/questions/sort1.php
EDIT:
I noticed that while my solution works well for my case, the output is slightly different from the accepted answer (http://www.sqlfiddle.com/#!4/d935b8/2/0):
1
1
10
11
11
12
31
100
110
114
300
A14
A18
4200
A170
(null)
(null)
4200 should come after 300. For my situation this is good enough, but this may not always be the case.
Based on the previous solution:
SELECT column
FROM table
ORDER BY LPAD(column, (SELECT MAX(LENGTH(column)) FROM table)) ASC
The advantage of this approach is that you don't need know the table column size.

Resources