Invalid Column Name in union clause - sql

I am trying to add a fixed value 'ALLE' to my column with a union clause, but I get an error:
Invalid column name BoltPattern
at my order by clause
How exactly do I do this?
SELECT 'ALLE'
UNION
SELECT BoltPattern
FROM [OminiTire].[Data].[WheelData]
WHERE BoltPattern IS NOT NULL
GROUP BY BoltPattern
ORDER BY
CASE
WHEN BoltPattern = 'ALLE'
THEN 1
ELSE 2
END, BoltPattern

I recommend using a subquery . . . and union all:
SELECT BoltPattern
FROM ((SELECT 'ALLE' as BoltPattern, 1 as ord)
UNION ALL
(SELECT DISTINCT BoltPattern, 2 as ord
FROM [OminiTire].[Data].[WheelData]
WHERE BoltPattern is not null
)
) x
ORDER BY ord, BoltPattern;
Notes:
UNION incurs overhead to remove duplicates. UNION ALL does not.
I find SELECT DISTINCT to be more succinct than using the GROUP BY.
The subquery allows you to define the explicit ordering -- easier to maintain (in my opinion) than a complicated CASE expression.

Related

use distinct and order by in STRING_AGG function

I am trying the string_agg a column while at the same time ordering the column and only show unique values. Consider the following demo. IS there a syntax issue or is this simply not possible with the method I am using?
SELECT STRING_AGG(DISTINCT foo.a::TEXT,',' ORDER BY foo.a DESC)
FROM (
SELECT 1 As a
UNION ALL
SELECT 1
UNION ALL
SELECT 1
UNION ALL
SELECT 2
) AS foo
[2019-11-22 13:29:32] [42P10] ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
[2019-11-22 13:29:32] Position: 53
The error message is quite clear. The expression that you use in the ORDER BY clause must also appear in the aggregated part.
You could do:
SELECT STRING_AGG(DISTINCT foo.a::TEXT, ',' ORDER BY foo.a::TEXT DESC)
FROM (
SELECT 1 As a
UNION ALL SELECT 1
UNION ALL SELECT 1
UNION ALL SELECT 2
) AS foo
Demo on DB Fiddle
While this will work, the problem with this solution is that it will order numbers as strings, that do not have the same ordering rules. String wise, 10 is less than 2.
Another option is to use arrays: first, ARRAY_AGG() can be used to aggregate the numbers (with proper, numeric ordering), then you can turn it to a comma-separated list of strings with ARRAY_TO_STRING().
SELECT ARRAY_TO_STRING(ARRAY_AGG(DISTINCT a ORDER BY a DESC), ',')
FROM (
SELECT 1 As a
UNION ALL SELECT 1
UNION ALL SELECT 1
UNION ALL SELECT 2
) AS foo
Demo on DB Fiddle

how to show null value at the end when using union all in sql

I am using this code to list numbers ASC and null values listing after the value in ms sql:
ORDER BY -ur.sira_no DESC
But if i use two select query with "UNION ALL" and than my query is not working.
Error:
ORDER BY items must appear in the select list if the statement contains a UNION, INTERSECT or EXCEPT operator.
How can we order null values after the numbers using UNION ALL?
Use a subquery:
select x.*
from ((select . . .
) union all
(select . . .
)
) x
ORDER BY - x.sira_no DESC;
However, I would recommend being more explicit:
ORDER BY (CASE WHEN sira_no IS NOT NULL THEN 1 ELSE 2 END),
sira_no ASC
in your original query. SQL Server allows you to order by column names in a union all query, but not on expressions.

Order by with union showing error incorrect syntax with union

select *
from student_details
where student_rollnumber in(644,1,2)
order by student_rollnumber
union
select *
from student_details
where student_rollnumber not in(644,1,2) ;
When you use ORDER BY with UNION it should be at the end.
select *
from student_details
where student_rollnumber in(644,1,2)
union
select *
from student_details
where student_rollnumber not in(644,1,2)
order by student_rollnumber;
If student_rollnumber is NOT NULL then your query is the same as:
select DISTINCT *
from student_details
order by student_rollnumber;
If you want those three students first, then use order by with case, not union:
select sd.*
from student_details sd
order by (case when sd.student_rollnumber in (644,1,2) then 1 else 2 end),
sd.student_rollnumber ;
There are several reasons why your approach is bad:
A SQL result set is unordered unless the entire query ends with an order by.
UNION is not efficient, because it has the overhead of removing duplicates.
Even a UNION ALL is not always guaranteed to return the first subquery values first.

how to sort by case insensitive alphabetical order using COLLATE NOCASE

I am trying to sort alphabetically case insensitive using COLLATE NOCASE
but getting error
ORA - 00933 SQL command not properly ended.
below is the query I am firing:
SELECT LPN.LPN_ID,
LPN.TC_ORDER_ID,
ORDERS.D_NAME,
ORDERS.PURCHASE_ORDER_NUMBER AS ORDER_PURCHASE_ORDER_NUMBER,
ORDERS.D_NAME AS D_NAME_2, LPN.LPN_NBR_X_OF_Y
FROM ORDERS ORDERS,
LPN LPN
WHERE ORDERS.ORDER_ID=LPN.ORDER_ID
ORDER BY ORDERS.D_NAME COLLATE NOCASE DESC
I checked here to try this but still getting error
How to use SQL Order By statement to sort results case insensitive?
Any suggestions please ?
Oracle does not support COLLATE NOCASE option of the order by clause. To be able to perform case-insensitive ordering you have two options:
Set NLS_COMP='ANSI' and 'NLS_SORT=BINARY_CI', CI suffix means case-insensitive, session or system wide by using alter session or alter system statement:
alter session set nls_comp='ANSI';
alter session set nls_sort='BINARY_CI';
with t1(col) as(
select 'A' from dual union all
select 'a' from dual union all
select 'b' from dual union all
select 'B' from dual
)
select *
from t1
order by col
Result:
COL
---
A
a
b
B
Change case of the character literal by using either upper() or lower() function.
with t1(col) as(
select 'A' from dual union all
select 'a' from dual union all
select 'b' from dual union all
select 'B' from dual
)
select *
from t1
order by upper(col)
result:
COL
---
A
a
b
B
Edit
but i need the UpperCase to preceed any LowerCase eg. Alan, alan, Brian, brian, Cris
This is not the case-insensitive ordering, rather quite contrary in some sense. As one of the options you could do the following to produce desired result:
with t1(col) as(
select 'alan' from dual union all
select 'Alan' from dual union all
select 'brian' from dual union all
select 'Brian' from dual union all
select 'Cris' from dual
)
select col
from ( select col
, case
when row_number() over(partition by lower(col)
order by col) = 1
then 1
else 0
end as rn_grp
from t1
)
order by sum(rn_grp) over(order by lower(col))
Result:
COL
-----
Alan
alan
Brian
brian
Cris
COLLATE NOCASE does not work with Oracle, Try this:
SELECT LPN.LPN_ID,
LPN.TC_ORDER_ID,
ORDERS.D_NAME,
ORDERS.PURCHASE_ORDER_NUMBER AS ORDER_PURCHASE_ORDER_NUMBER,
ORDERS.D_NAME AS D_NAME_2,
LPN.LPN_NBR_X_OF_Y
FROM orders orders,
lpn lpn
where orders.order_id=lpn.order_id
ORDER BY lower(orders.d_name) DESC;
Since 10g there is a function NLSSORT which does pretty much what Nicholas Krasnov described but doesn't require altering the system or session.
so you can try something like this:
SELECT LPN.LPN_ID, LPN.TC_ORDER_ID, ORDERS.D_NAME, ORDERS.PURCHASE_ORDER_NUMBER
AS ORDER_PURCHASE_ORDER_NUMBER, ORDERS.D_NAME AS D_NAME_2, LPN.LPN_NBR_X_OF_Y
FROM ORDERS ORDERS, LPN LPN
WHERE ORDERS.ORDER_ID=LPN.ORDER_ID
ORDER BY nlssort(ORDERS.D_NAME, 'NLS_SORT = binary_ci') desc
Note you can't use this directly in a UNION or you'll get the following error:
ORA-01785: ORDER BY item must be the number of a SELECT-list
expression.
Instead, you need to wrap it:
SELECT * FROM (SELECT a, b FROM x, y UNION SELECT c, d FROM m, n)
ORDER BY nlssort(a, 'nls_sort=binary_ci') DESC

Custom order after distinct statements

I want to make a custom order: IN, OUT, FINISHED.
If I left case statement I am getting in FINISHED, IN, OUT.
I found this solution but it does not work for me - I am getting error.
select distinct 'IN' as STATUS,
(select count(*) ...)
from table
UNION ALL
select distinct 'OUT',
(select count(*) ...)
from table
UNION ALL
select distinct 'FINISHED',
(select count(*) ...)
from table
order by
case STATUS
when 'IN' then 1
when 'OUT' then 2
when 'FINISHED' then 3
end
The query that you provided has some syntax irregularities. I think the following solves your problem:
select *
from ((select distinct 'IN' as statusA, (select count(*) ...
from table
)
union all
(select distinct 'OUT', (select count(*) ...)
from table
)
union all
(select distinct 'FINISHED', (select count(*) ...)
from table
)
) t
order by status,
(case STATUSA when 'IN' then 1
when 'OUT' then 2
when 'FINISHED' then 3
end)
Your original problem could have several causes. You were missing the 'IN' in the first subquery. You are missing the comma after status in the order by. And, some databases apply the final order by in a series of unions to only the last query (although I think DB2 does this correctly).