ORDER BY with column number in case - sql

I have a select with the following order by:
ORDER BY 4 DESC, case when (5 is null ) then 1 else 2 end, 5 desc,10
However, apparently, the fifth column is used as the literal 5, unlike the other expressions:
A constant expression was encountered in the ORDER BY list, position 2.
What should I do here?
Thanks!

Use the actual column names! That way, any future changes to the columns in your select don't break your order by.
And if you don't believe me: https://sqlblog.org/2009/10/06/bad-habits-to-kick-order-by-ordinal

This is an all around bad idea. Use the column name no matter how long it is.It would be a maintenance nightmare otherwise.You should try to avoid using dynamic sql.

Related

SQL Order By Except When You Don't

I want to retrieve a full table with some of the values sorted. The sorted values should all appear before the unsorted values. I though I could pull this off with a UNION but order by is only valid to use after unioning the table and my set of data isn't set up such that that is useful in this case. I want rows with a column value of 0-6 to show up sorted in DESC order and then the rest of the results to show up after that. Is there some way to specify a condition in the order by clause? I saw something that looked close to what I wanted to so but I couldn't get the equality condition working in sql. I'm going to try to make a query using WHEN cases but I'm not sure if there's a way to specify a case like currentValue <= 6. If anyone has any suggestions that would be awesome.
You could do something like this:
order by (case when currentValue <= 6 then 1 else 0 end) desc,
(case when currentValue <= 6 then column end) desc
The first puts the values you care about first. The second puts them in sorted order. The rest will be ordered arbitrarily.
Try this:
SELECT *
FROM yourdata
ORDER BY CASE WHEN yourColumn BETWEEN 0 AND 6 THEN yourColumn ELSE -1 End Desc
One RDBMS-agnostic solution would be to add a second field that takes the same value as the field you wish to sort when that field is less than or equal to six. Then just sort by that field.

oracle PL/SQL: sort order by issue [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
oracle PL/SQL: sort rows
I run this query:
Select a.product, sum(
case
when b.id=1 then round(c.sales,3)
else 0
end) as Q1_2008,
sum(
case
when b.id=2 then round(c.sales,3)
else 0
end) as Q2_2008,
sum(
case
when b.id=3 then round(c.sales,3)
else 0
end) as Q3_2008
from products a, quarters b, sales c
where
a.id=c.PRODUCT_ID and
b.id=c.QUARTER_ID
group by a.product
order by product
But my Product column is not in order.
PRODUCT
PROD_1
PROD_10
PROD_2
PROD_3
PROD_4
PROD_5
PROD_6
PROD_7
PROD_8
PROD_9
PROD_10 is the second row when it should be at the end. How can I fix this?
That is in order. Order by for numbers and strings are different.
11 is less than 2 in a string, so produect_10 is placed before your product_2. If you wish to sort by a number in a string, you must pull that number out and sort on it by itself as a number.
Here is an example of an "order by" statement that does what you want:
order by cast(substr(product, 5, 100) as int)
use substr to pick out the numeric portion of the string.
use to_number to turn it into a number
sort by that.
If you really must use strings (given this same question has been asked a few minutes ago), then you may have to go some byzantine split/convert route. i.e. take the substring before _, chuck it away, convert remaining part to integer, order by that. I wouldn't want to vouch for it being a sustainable solution though.
What Limey said is correct. If you want to order the names correctly then either rename the strings so that they are padded by 0s...for example PROD_01, PROD_01, PROD_02, PROD_03, PROD_10. this way all will be in order.
else split, to_number and then Order the number part of the product.(this will only work in case you have common string as prefix as the product name)

What does ORDER BY 5 DESC mean?

SELECT Departamentos.Nome_Dep,
Funcionarios.Nome AS Funcionario,
Funcionarios.Salario,
AVG(Funcionarios.Salario) OVER(PARTITION BY Departamentos.Nome_Dep) "Média por Departamento"
Salario - AVG(Funcionarios.Salario) OVER(PARTITION BY Departamentos.Nome_Dep) "Diferença de Salário" FROM Funcionarios
INNER JOIN Departamentos
ON Funcionarios.ID_Dep = Departamentos.ID
ORDER BY 5 DESC
The Order By 5 is throwing me off. I've never anything like it. Order By [colunmname] yes, but Order By [number], never seen before. I pulled this off an article.
Note: This is T-SQL.
Source: Window Functions in SQL Server 2005, 2008, 2012
This will order by the 5th field in this SELECT statement
Order by the 5th column in the result set.
The number represents the index of the column within your select list.
Source: http://mattberseth.com/blog/2007/05/quick_tip_order_by_1_descendin.html
Order by fifth column in the result set descending.
It is the SORTING BY RELATIVE POSITION.
You can use the SQL ORDER BY clause to sort by relative position in the result set, where the first field in the result set is 1. The next field is 2, and so on.
Here in this case Order by 5th field in the result set.
Go through http://www.techonthenet.com/sql/order_by.php
about sql order by.
Useful when a similar column name has become a calcuated output field,
In the following example, it would be confusing if say 'order by numberofVioation' as this column name has just become the name of a query output SUM field (of the same old column data)
So it become useful in calculated output field
Example:
Original fields:
name| Type| RiskLevel| Date| results| violations|
/* now add an extra Sum of Violation for each type, pls note 'order by 2 desc' refers to order by the 2nd queried column, ie hi to low */
select Type, sum(numberOfViolations) as numberOfViolations
from restaurantsTable
group by Type
order by 2 desc
Order by 5th field in the result set.

designedly big value in SQL

Ok, I have to put null values last. The query should run under Oracle and MySQL.
I've already came up with
ORDER BY
CASE WHEN some_table.ord IS NULL THEN 9999999999 ELSE some_table.ord END
I should use value > max(some_table.ord) instead of 9999999999.
I think subquery to determine this value is too ugly here.
If this was C++ I can use some macro like INT_MAX for this purpose. Can you name its cross-DBMS SQL twin?
UPDATE
the question is if can I put something .. beautiful instead of 9999999999, so that query will work both in Oracle and MySQL,
not how to put null values last
Use an extra column for the null flag:
order by
case when some_table.ord is null then 2 else 1 end ,
some_table.ord
Or, if you have enough knowledge of the values that this column can take, just hard-code a number that is larger than anything in there:
order by coalesce(some_table.ord, 9999999999)
In Oracle, it's simply
ORDER BY some_table.ord NULLS LAST
Something like the following might work:
SELECT S.VAL1, S.VAL2, S.VAL3, COALESCE(S.ORD, O.MAX_ORD+1) AS ORD
FROM SOME_TABLE S,
(SELECT MAX(ORDER) AS MAX_ORD FROM SOME_TABLE) O
WHERE S.whatever = whichever AND
S.something <> something_else
ORDER BY ORD
Not sure if MySQL allows sub-queries in the FROM list. The idea here is to avoid the use of a magic value to handle the NULL case.
Share and enjoy.

How to do this query in T-SQL

I have table with 3 columns A B C.
I want to select * from this table, but ordered by a specific ordering of column A.
In other words, lets' say column A contains "stack", "over", "flow".
I want to select * from this table, and order by column A in this specific ordering: "stack", "flow", "over" - which is neither ascending nor descending.
Is it possible?
You can use a CASE statement in the ORDER BY clause. For example ...
SELECT *
FROM Table
ORDER BY
CASE A
WHEN 'stack' THEN 1
WHEN 'over' THEN 2
WHEN 'flow' THEN 3
ELSE NULL
END
Check out Defining a Custom Sort Order for more details.
A couple of solutions:
Create another table with your sort order, join on Column A to the new table (which would be something like TERM as STRING, SORTORDER as INT). Because things always change, this avoids hard coding anything and is the solution I would recommend for real world use.
If you don't want the flexibility of adding new terms and orders, just use a CASE statement to transform each term into an number:
CASE A WHEN 'stack' THEN 1 WHEN 'over' THEN 2 WHEN 'flow' THEN 3 END
and use it in your ORDER BY.
If you have alot of elements with custom ordering, you could add those elements to a table and give them a value. Join with the table and each column can have a custom order value.
select
main.a,
main.b,
main.c
from dbo.tblMain main
left join tblOrder rank on rank.a = main.a
order by rank.OrderValue
If you have only 3 elements as suggested in your question, you could use a case in the order by...
select
*
from dbo.tblMain
order by case
when a='stack' then 1
when a='flow' then 2
when a='over' then 3
else 4
end