why Order by does not sort? - sql

I have a query below, I want it to sort the data by id, but it doesn't sort at all.
Select distinct ec.category,ec.id
from print ec
order by ec.id asc
What could be the reason?
this is the output :

Looking at your data, the column data type is a varchar, aka 'text'.
If it is text, it sorts like text, according to the place the character occurs in the character set used.
So each column is ordered on the first character, then the second, etc. So 2 comes after 11.
Either make the column a numeric data type, like number, or use to_number in the sorting:
select distinct ec.category,ec.id
from print ec
order by to_number(ec.id)

The difference lies in the way varchar and number are sorted. in your case, since you have used varchar data type to store number, the sorting is done for the ASCII values.
NUMBERS when sorted as STRING
SQL> WITH DATA AS(
2 SELECT LEVEL rn FROM dual CONNECT BY LEVEL < = 11
3 )
4 SELECT rn, ascii(rn) FROM DATA
5 order by ascii(rn)
6 /
RN ASCII(RN)
---------- ----------
1 49
11 49
10 49
2 50
3 51
4 52
5 53
6 54
7 55
8 56
9 57
11 rows selected.
SQL>
As you can see, the sorting is based on the ASCII values.
NUMBER when sorted as a NUMBER itself
SQL> WITH DATA AS(
2 SELECT LEVEL rn FROM dual CONNECT BY LEVEL < = 11
3 )
4 SELECT rn, ascii(rn) FROM DATA
5 ORDER BY rn
6 /
RN ASCII(RN)
---------- ----------
1 49
2 50
3 51
4 52
5 53
6 54
7 55
8 56
9 57
10 49
11 49
11 rows selected.
SQL>
How to fix the issue?
Change the data type to NUMBER. As a workaround, you could use to_number.
Using to_number -
SQL> WITH DATA AS(
2 SELECT to_char(LEVEL) rn FROM dual CONNECT BY LEVEL < = 11
3 )
4 SELECT rn, ascii(rn) FROM DATA
5 ORDER BY to_number(rn)
6 /
RN ASCII(RN)
--- ----------
1 49
2 50
3 51
4 52
5 53
6 54
7 55
8 56
9 57
10 49
11 49
11 rows selected.
SQL>

Make sure the type of your "id" column is int. (integer = number)
Right now it is probably text, char or varchar(for text, strings).
You can't sort numbers alphabetically or strings/text chronologically like you are trying now.

when you sort a string datatype that has in values it produce result as
1
10
11
2
21 etc...
Hence
Change your Id datatype to int/bigint

You can only just cast/convert the datatype in a query
Select distinct ec.category,ec.id
from print ec
order by cast(ec.id as int) asc

Related

Group rows using the cumulative sum of a third column

I have a table with two columns:
sort_column = A column I use for sorting
value_column = My metric of interest (a positive integer)
Using SQL, I need to create contiguous groups of rows, ordered by sort_column, such that the sum of value_column within each group is the largest possible but staying below 100 (100 not included).
Find below an example of my desired result.
Thanks
sort_column
value_column
desired_result
1
53
1
2
25
1
3
33
2
4
25
2
5
10
2
6
46
3
7
9
3
8
49
4
9
48
4
10
53
5
11
33
5
12
52
6
13
29
6
14
16
6
15
66
7
16
1
7
17
62
8
18
57
9
19
47
10
20
12
10
Ok, so after a few lengthy attempts, I came to the conclusion the task is impossible with pure SQL, because a given value of the desired column depends on previous values of that same column, in a way that cannot be obtained from the first two columns alone, so the problem is impossible to tackle without using a recursive CTE, which BigQuery does not support.
I solved the issue by writing a javascript UDF for the task. It seems to be working fine and produces the expected results.
Many thanks everyone!

Sort String column which has numbers and Alphabets( Oracle SQL)

I want to sort a string column which can include both numbers and alphabets.
SQL Script:
select distinct a.UoA, b.rating , b.tot from omt_source a left join
wlm_progress_Scored b
on a.UoA = b.UoA
where a.UoA in (select UoA from UserAccess_dev
where trim(App_User) = lower(:APP_USER))
order by
regexp_substr(UoA, '^\D*') ,
to_number(regexp_substr(UoA, '\d+'))--);
Output I'm currently getting:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
23
26B
26A
27
28
30
31
32
33
34B
34A
But, I want 26 and 34 to be in this order
26A
26B
34A
34B
Any suggestion will be much helpful
Thanks
If your first order by clause ensures that the primary sort order is based on the numerical component of the UoA field, then your second order clause could actually be just the UoA field itself. I.e.
order by
regexp_substr(UoA, '^\D*'), UoA;

Select every ten steps SQL

I have the following table:
----------------------------------------------
oNumber oValue1
----------------------------------------------
1 54
2 44
3 89
4 65
ff.
10 33
11 22
ff.
20 43
21 76
ff.
100 45
I want to select every 10 value in oNumber. So the result should be:
----------------------------------------------
oNumber oValue1
----------------------------------------------
10 33
20 43
ff.
100 45
Also, oNumber is not a sequence number. It's just a value. Even it isn't a sequence number, 10, 20, 30 and so on will always appear under oNumber field.
Does anyone know how is the tsql for this case?
Thank you.
select * from table where oNumber % 10 = 0
https://msdn.microsoft.com/en-us/library/ms190279.aspx
Use the "Modulo" operator - %. So in this case, the answer would be something like:
SELECT * FROM table WHERE oNumber % 10 = 0
This will only load if oNumber is a number divisible by ten (and therefore has a remainder zero).
In the case you simply want multiples of 10, then just use the modulo operator as stated by Daniel and Ian.
select *
from table
where oNumber % 10 = 0;
However, I felt that you could be alluding to the fact that you want to get every 10th item in your list. If that's the case, which it may be not, you would simply just sequence your set based on oNumber and use the modulo operator.
select *
from (
select *,
RowNum = row_number() over (order by oNumber)
from table) a
where RowNum % 10 = 0;

sql server 2008 - calculated and ordered list needs to return only 2 entries per supplier

I have a dataset like below, but longer. I want to ensure I am picking the 'fleet_id' in terms of their 'StarDriver' value overall, but I want to return only two results for each 'supplier_id' and return a max of 20 in total.
(I'm sorry I didnt work out how to copy the below in proper formatting, couldn't find from toolbar above and google results were about copying data; would also be grateful if someone would point out how)
fleet_id supplier_id Ratings Driver Punctuality Car StarDriver
19442 151 10 5 5 5 5
19634 151 11 5 5 5 5
19437 151 12 5 5 5 5
12832 10 14 5 4.92857142857143 5 4.97619047619048
12217 111 10 5 5 4.9 4.96666666666667
21135 158 19 5 4.89473684210526 5 4.96491228070175
19436 151 14 4.85714285714286 5 5 4.95238095238095
12239 111 12 4.91666666666667 5 4.91666666666667 4.94444444444445
10520 92 12 4.91666666666667 5 4.91666666666667 4.94444444444445
19997 151 12 5 5 4.83333333333333 4.94444444444444
To limit to the top 2 for each supplier, use row_number(). This will enumerate the rows and you can choose just two with where seqnum <= 2.
The rest of the query is just selecting 20 rows based on a field:
select top 20 t.*
from (select t.*,
row_number() over (partition by supplier order by StarDriver desc) as seqnum
from table t
) t
where seqnum <= 2
order by StarDriver;

SQL Query- Partition into groups & calculate max- min value

Need your help with a SQL query in Oracle db. I have data that I want to partition into groups when event = "Start". E.g. Row 1-6 is a group, row 7-9 is a group. I want to ignore rows with event = "Ignore". Finally I want to calculate max(Value)-min(Value) for these groups. I dont have any way to group the data.
Can this be achieved? Is it possible to use partition by Event = start. Same data is below:
Row Event Value Required Result is max-min of value
1 Start 10
2 A 11
3 B 12
4 C 13
5 D 14
6 E 15 5
--------------------------------------------
7 Start 16
8 A 18
9 B 20 4
--------------------------------------------
10 Start 27
11 A 30
12 B 33
13 C 34 7
--------------------------------------------
14 Ignore 35
--------------------------------------------
15 Ignore 36
--------------------------------------------
16 Start 33
17 A 34
18 B 35
19 C 36
20 D 37
21 E 38 5
--------------------------------------------
Yes, you can do this in SQL.
The following query first finds the group that a row is in, by finding the largest start before the row id. This version uses a correlated subquery for this calculation.
It then does the grouping on the id and does the calculation.
select groupid, max(value) - min(value)
from (select t.*,
(select max(row) from t t2 where t2.row < t.row and t2.event = start
) as groupid
from t
) t
where event <> 'IGNORE'