How to sort top 4 values with SQL Server which contains negative numbers - sql

Input file
SN ID
------------
1 55
2 -25
3 62
4 -0.05
5 0.0
Output file should be after sorting
SN ID
-------
3 62
1 55
5 0.0
4 -0.05
2 -25
Using this SQL Server command need to modify by logic
select top 4 *
from filename
order by ID desc

It sounds as though perhaps your ID column is actually some sort of text, rather than numeric, type. If so, then casting the column to a decimal and then sorting should fix the problem:
SELECT TOP 4 *
FROM filename
ORDER BY CAST(ID AS DECIMAL(10,4)) DESC;
Note that if the above query does work, then you should seriously consider not storing numeric information as text.

You are missing a WHERE clause. If you need to filter only by negative values just add the following:
select top 4 *
from filename
where ID < 0
order by ID desc

Related

SQL compares the value of 2 columns and select the column with max value row-by-row

I have table something like:
GROUP
NAME
Value_1
Value_2
1
ABC
0
0
1
DEF
4
4
50
XYZ
6
6
50
QWE
6
7
100
XYZ
26
2
100
QWE
26
2
What I would like to do is to groupby group and select the name with highest value_1. If their value_1 are the same, compare and select the max with value_2. If they're still the same, select the first one.
The output will be something like:
GROUP
NAME
Value_1
Value_2
1
DEF
4
4
50
QWE
6
7
100
XYZ
26
2
The challenge for me here is I don't know how many categories in NAME so a simple case when is not working. Thanks for help
You can use window functions to solve the bulk of your problem:
select t.*
from (select t.*,
row_number() over (partition by group order by value1 desc, value2 desc) as seqnum
from t
) t
where seqnum = 1;
The one caveat is the condition:
If they're still the same, select the first one.
SQL tables represent unordered (multi-) sets. There is no "first" one unless a column specifies the ordering. The best you can do is choose an arbitrary value when all the other values are the same.
That said, you might have another column that has an ordering. If so, add that as a third key to the order by.

Replace a column value with random values

I want to replace values in a column with randomized values
NO LINE
-- ----
1 1
1 2
1 3
1 4
2 1
2 2
3 1
4 1
4 2
I want to randomize column NO and replace with random values. I have 5 million records and doing something like below script gives me 5 million unique NO's but as you can see NO is not unique and i want the same random value assigned for the same NO.
UPDATE table1
SET NO= abs(checksum(NewId())) % 100000000
I want my resultant dataset like below
NO LINE
------ ----
99 1
99 2
99 3
99 4
1092 1
1092 2
3456 1
41098 1
41098 2
I would recommend rand() with a seed:
UPDATE table1
SET NO = FLOOR(rand(NO) * 100000000);
This runs a slight risk of collisions, so two different NO rows could get the same value.
If the numbers do not need to be "random" you can give them consecutive values in an arbitrary order and avoid collisions:
with toupdate as (
select t1.*,
dense_rank() over (order by rand(NO), no) as new_no
from t
)
update toupdate
set no = new_no;

Compare column entry to every other entry in the same column

I have a Column of values in SQLite.
value
-----
1
2
3
4
5
For each value I would like to know how many of the other values are larger and display the result. E.g. For value 1 there are 4 entries that have higher values.
value | Count
-------------
1 | 4
2 | 3
3 | 2
4 | 1
5 | 0
I have tried nested select statements and using the Count(*) function but I do not seem to be able to extract the correct levels. Any suggestions would be much appreciated.
Many Thanks
You can do this with a correlated subquery in SQLite:
select value,
(select count(*) from t t2 where t2.value > t.value) as "count"
from t;
In most other databases, you would use a ranking function such as rank() or dense_rank(), but SQLite doesn't support these functions.

Creating sequentially increasing groups based on number change

How can I code this in oracle SQL?
I have the below data
Current Result
I want to generate a result that looks like the following:
Desired Result
So, I essentially want the group ID to increase as the row number changes back to 1. I am trying to use row_number, rank() and partition functions but it is not working properly. Desperate for help!
Thanks
EDIT (by Gordon):
The original question had the data in question. It is much, much better to have the values in the question as text than to refer to an image, so I'm adding it back in:
Code Row Number
214 1
214 2
210 1
210 2
210 3
214 1
I want to generate a result that looks like the following:
Code Row Number Group Id
214 1 1
214 2 1
210 1 2
210 2 2
210 3 2
214 1 3
In order to do what you want, you need a column that specifies the ordering of the rows in the table. Let me assume that you have an id or creation date or something similar.
If so, then what you want is simply a cumulative sum of the number of times that the second column is 1:
select t.*,
sum(case when RowNumber = 1 then 1 else 0 end) over (order by id) as GroupId
from t;
it's still not clear which field is ID because if it's rownumber as you said it's not going work the way that you have in expected output
create table test (id int , code int, rownumber int);
insert into test values (1,214,1);
insert into test values (2,214,2);
insert into test values (3,210,1);
insert into test values (4,210,2);
insert into test values (5,210,3);
insert into test values (6,214,1);
select s.code, sum(add_group) over (order by id) from (
select id, code, case when rownumber=1 then 1 else 0 end as add_group from test
order by id
) s
CODE SUM(ADD_GROUP)OVER(ORDERBYID)
1 214 1
2 214 1
3 210 2
4 210 2
5 210 2
6 214 3
btw the asnwer of #Gordon Linoff works better and exactly as you want but you need add additional field for order by

How to find a field with some specific value in another field in sql

I have 2 columns MessageID and FlowStatusID.
I want to find MessageID's which have a FlowStatusID is one specific value with a special sequence.
For example I want to find MessageID's where the FlowStatusID contains the sequence of these numbers: 105,81,21
MessageID FlowStatusID
-------------------------
1 11
1 105
2 105
2 81
2 21
3 81
4 105
4 81
4 21
5 21
5 105
The result must be 2, 4
You don't mention the database type but I've found some other tickets which explain how to concatenate values from multiple records.
Postgress: Concatenate multiple result rows of one column into one, group by another column
Oracle : SQL Query to concatenate column values from multiple rows in Oracle
You can use this concatenated field in a condition with an equality match:
where myconcatresult = '21,81,105'
I don't know how this will perform :)
Try like this
select MessageIDfrom t group by MessageID having count(*) =3 ;
Or
select MessageID from (
select t.MessageID from t where FlowStatusID=21
union all
select t.MessageID from t where FlowStatusID=81
union all
select t.MessageID from t where FlowStatusID=105 )
as tt group by MessageID having count(*) =3