Plsql cursor active set results are not in order - sql

I'm investigating an prod issue which has data as below in DB:
11
22
33
44
55
The cursor brings out the active set result in a random order sometimes as below :
44
55
11
22
33
Is this possible and valid?

The only way to make sure that query will return rows in desired order is to - guess what? - use the order by clause.
So:
declare
cursor c1 is
select value
from your_table
order by value; --> this
Anything else is just pure luck (whether you will, or will not, get rows the way you thought you should).

Related

How do I input an incremented value into selected column in Oracle SQL and/or PL/SQL?

I am in the process of updating a huge DB and can not for the life of me figure this out.
SELECT rank_column FROM schema.table
WHERE id IN (x,y,z,a,b,c) AND lll AND ooo
I'm a little stuck here since I need to set rank_column for x to be updated to 1A, rank_column for y to be 2A, z to be 3A, etc.
There are only 30 or so values here so I can do them by hand, but on the more difficult note, I also need to need to rank the values NOT in this list and we're talking about somewhere near 300,000+. The order for these should not matter, but how do I set the first read row to 1Z, the second to 2Z, the third to 3Z, etc? Thank you for any help it would be much appreciated!
I attempted to use pl/sql but every single time, it updates with the very same number so I might have 1B for all when I want 1B,2B,3B etc. I need something like this down below except I need to iterate each for each row. I attempted to put iterate:=iterate+1 inside of the set statement so everytime it sets rank it will iterate that rank, but I keep returning "missing equal sign" on the set line right over the equal sign.
DECLARE
iterate number:=1;
BEGIN
UPDATE schema.table
SET rank = iterate||'A'**,ITERATE = ITERATE + 1**
WHERE ID IN (11111,22222,33333,44444,55555,66666,777777,88888,99999)
AND type = '01'
AND manufacturer = '000111'
AND indicator = '0';
iterate:= iterate +1;
END;
Are you looking for something like this?
update tab_lvl set rank=rownum||'A' where id in (30,40,50,60,70,80,90,100);
8 rows updated.
select id,rank from tab_lvl where id in (30,40,50,60,70,80,90,100);
ID RANK
---------- ---------------
30 1A
40 2A
50 3A
60 4A
70 5A
80 6A
90 7A
100 8A
8 rows selected.

How to query a varchar2 field which has numerical values using order by desc in sql

I have table with varchar 2 datatypes column now i want to fetch the records column and duration column in order by desc order but not working wat i expected.
Query :
select * from sampletable2
where code = 'C'
order by duration desc ;
QUERY output looks like below :
KeyNumber ID Code BRANCH records Duration
A907654234 4 C ALA 100 99
A875678235 3 C PHE 30 9
A123456789 1 C HIE 78 45
A907863544 5 C VAL 50 23
what i want is like :
KeyNumber ID Code BRANCH records Duration
A907654234 4 C ALA 100 99
A123456789 1 C HIE 78 45
A907863544 5 C VAL 50 23
A875678235 3 C PHE 30 9
can someone correct me where im going wrong and correct my query?
How about
order by to_number(duration) desc
It should work, if duration contains numbers. Also, if that's so, why do you keep numbers in a VARCHAR2 column?
If column contains something else, and not only numbers, then see whether regular expressions help. For example:
order by to_number(regexp_substr(duration, '\d+')) desc, duration
You can use to_number and on conversion error as follow:
order by to_number(duration default -1 on conversion error) desc
With this solution, you will get all the non number value records at last.
This answers the original version of the question.
I don't see how your query is producing the first result. But if you want to sort by numeric values, then you can convert to a number:
order by to_number(records) desc, to_number(duration) desc ;
That said, a much better approach is to fix the data model. You should not be storing numbers as strings.

Calc a Moving Average of Temps from a 24 hour (cyclic) column of entries?

I am amazed this question doesn't seem to have been asked before, but if so, my pretty exhaustive searches have not discovered it.
I have a simple ring buffer of temperatures in a column from which I want calculate the average value.
The sql table looks like this (column names shown in top row) ...
uid Temp
1 70
2 70
3 70
4 70
5 70
6 69
7 69
8 69
9 69
10 69
Every time I obtain a new temperature, I want to shift the "Temp" column up one row before writing the newest value into slot '10' so I can get the average value of the column data.
There must be a simple way to do this, that I haven't figured out yet. :-(
You can do the shift like this:
delete from buffer where id = 1;
update buffer set id = id - 1;
insert into buffer(id, temp) values(10, #temp);
However, I would keep all the temperature values and use another method to get the 10-unit moving average.
Got it !!
-- shift column values up one row.
UPDATE [myTable]
SET [temp] = (SELECT [temp]
FROM [myTable] AS s2
WHERE s2.[uid] = ([myTable].[uid] +1))
WHERE [uid] <= 9;
This moves just the specific cells up one row, as desired.
It was more complicated than I thought it would be, but this seems to work exactly as I needed.
[:-)}

Selecting filtered values from Oracle using ROWNUM

I have a requirement wherein i need to find the record number of the records that are returned from the resultset. I know that i can use ROWNUM to get the record number from the resultset but my issue is slightly different. below are the details
Table : ProcessSummary
Columns:
PS_PK ProcessId StepId AsscoiateId ProcessName AssetAmount
145 25 50 Process1 3,500.00
267 26 45 Process2 4,400.00
356 27 70 Process3 2,400.00
456 28 80 90 Process4 780.00
556 29 56 67 Process5 4,500.00
656 45 70 Process6 6,000.00
789 31 75 Process7 8,000.00
Now what i need to do is fetch all the records from the ProcessSummary Table when either of ProcessId OR StepId OR AssociateId is NULL. I wrote the below query
select * from ProcessSummary where ProcessId IS NULL OR StepId IS NULL OR AsscoiateId IS NULL
As expected i got 1st, 2nd, 3rd, 6th and 7th records in the resultset that got returned.
Now what i need is to get the records numbers 1,2,3,6,7. I tried to use the ROWNUM as below but i got the values of 1,2,3,4,5 and not 1,2,3,6,7.
select ROWNUM from ProcessSummary where ProcessId IS NULL OR StepId IS NULL OR AsscoiateId IS NULL
Is it possible to get the ROWNUM values in the sequence that i want and if yes then can you please let me know how can i do this. Also if ROWNUM cannot be used then what would be the other option that i can use to get the result in the form that i want.
Any help would be greately appericiated as i could not find much on the net or SO regarding this sort of requirement.
Thanks
Vikeng21
rownum is an internal numbering that gives you a row number based on the current query results only, so that numbering is not tied to a specific record, and it will change when you change the data or the query.
But the numbering you ask for is already in your table. It looks like you just need to SELECT PS_PK .. instead. PS_PK is the field in your table that contains the actual number you want.
You can generate a numbering using an analytical function, and then filter that query. You need some fields to order by, though. In this case I've chosen PS_PK, but it can be another field, like ProcessName or a combination of other fields as well.
select
*
from
(select
dense_rank() over (order by PS_PK) as RANKING,
p.*
from
ProcessSummary p)
where
ProcessId IS NULL OR StepId IS NULL OR AsscoiateId IS NULL
So, in this query, first a numbering is calculated for each row that is returned from the inner query. The numbering is returned as the field RANKING. And then the other query filters further, but still will return the field RANKING with the original numbering.
Instead of dense_rank there is also rank and row_number. The differences are subtle, but you can just experiment and read some docs here and here to learn about the differences and see which one fits you best.
Note that this might slow down your query, because the inner query first generates a number for each row in the table (there is no filtering on that level now).

SQL - Delete value if incremental pattern not met

I have a table with a column of values with the following sample data that has been pulled for 1 user:
ID | Data
5 Record1
12 NULL
13 NULL
15 Record1
20 Record12
28 NULL
31 NULL
35 Record12
37 Record23
42 Record34
51 NULL
53 Record34
58 Record5
61 Record17
63 NULL
69 Record17
What I would like to do is to delete any values in the Data column where the Data value does not have a start and finish record. So in the above Record 23 and Record 5 would be deleted.
Please note that the Record(n) may appear more than once so it's not as straight forward as doing a count on the Data value. It needs to be incremental, a record should always start and finish before another one starts, if it starts and doesnt finish then I want to remove it.
Sadly SQL Server 2008 does not have LAG or LEAD which would make the operation simpler.
You could use a common table expression for finding the non consecutive (non null) values, and delete them;
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY id) rn FROM table1 WHERE data IS NOT NULL
)
DELETE c1 FROM cte c1
LEFT JOIN cte c2 ON (c1.rn = c2.rn+1 OR c1.rn = c2.rn-1) AND c1.data = c2.data
WHERE c2.id IS NULL
An SQLfiddle to test with.
If you just want to see which rows would be deleted, replace DELETE c1 with SELECT c1.*.
...and as always, remember to back up before running potentially destructive SQL for random people on the Internet.