Issue in union operation - sql-server

I have a query in database like
SELECT 0 AS [DocumentType],'Select Document Type' [DocumentTypeX],0 ,0
UNION
SELECT dbo.tbDocumentType.*
FROM dbo.tbDocumentType where Site=#Site
It throws error message "All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists."

First and foremost rule for UNION Operation:
1.Both Query should have the same number of the resultset.
2.Respective Columns of both queries should have similar data types.
3.Never go with TableName.*.Instead Specify Column Names
Please check on that....

Instead of
SELECT dbo.tbDocumentType.*
Select the columns matching your UNION fields
SELECT dbo.tbDocumentType.[DocumentType],
dbo.tbDocumentType.[DocumentTypeX],
dbo.tbDocumentType.[Something1],
null -- Or use any value you want if doesnt have the column

Related

How to solve Oracle ORA-00904 Invalid identifier on Union where columns are from different datatypes

I have a query that results in single column with CLOB containing JSON object
select json_object( key 'casinos' VALUE
(select json_arrayagg(
json_object(
key 'code' VALUE cas.code, /*error invalid identifier*/
key 'name' VALUE cas.name,
key 'skins' VALUE coalesce (
(SELECT json_arrayagg(
json_object( key 'code' VALUE csk.code,
key 'name' VALUE csk.name
)
)
from CASINO.CASINOCLIENTSKINS csk
WHERE csk.casinocode = cas.code
), '[]')
FORMAT JSON )
from ( SELECT to_char(cas.code), cas.name FROM CASINO.CASINOS cas
UNION all SELECT 'default', 'Default casino' FROM DUAL
) cas
) returning clob
) responseJson
FROM DUAL
need to add dummy record, but cas.code column is from NUMBER datatype, dummy column is VARCHAR. Converting cas.code to char results in ORA-00904 Invalid identifier
In the SELECT statement you have TO_CHAR(....) but you didn't give it an alias. That SELECT does not output any column called CODE.
The solution is simple: SELECT TO_CHAR(CAS.CODE) AS CODE, .......
EDIT
After you do that, you will get another error, "Invalid number". That will be from the join condition
WHERE csk.casinocode = cas.code
because casinocode is number data type and cas.code is varchar2. Now cas.code has one value, the string 'default', which can't be converted implicitly to a number.
The solution is to wrap csk.casinocode within to_char() also, in this condition.
Question for you though. Since you are performing this join after you added the "default" row, and it's an inner join, the "default" row will be discarded by the join. So, why are you adding it at all?
You probably want an outer join there.
As a general strategy - you shouldn't try to debug your code when it's already wrapped within the JSON stuff. You aren't even getting your desired results as the output of a standard SQL query - fix that first, get it 100% right, and then wrap the results within JSON operators.

Order by in union clause

Could any one please help me I have been working on a query containing unions n joins of multiple tables.. I have got the desired results but I want to get these results in some specific order so the whole result is being orderd according to one column.
Here is the snippet of code I am working on:
select name, age
from UserUni
order by age
union all
select age, Name
from UserOffice
order by age
Just add an ORDER BY clause at the very end of the UNION query, and it should be applied to the entire query:
select name, age
from UserUni
union all
select name, age
from UserOffice
order by age
Note that I swapped the order of the columns appearing in the second half of the UNION query because it doesn't make sense to put age and name into the same column. It is generally a requirement in a UNION query that the types and number of all columns be the same in boths halves of the query. One exception might be MySQL, which might appear to allow mixing numbers and text, but even in this case some implicit type conversion would be happening underneath the hood.
when we are using we can not use order by with both statements. because union at the end give one result end so how is it possible to use two order by statements.
you can check details here.
https://finalcodingtutorials.blogspot.ae/2017/03/order-by-clause-with-union-in-sql-server.html
hopefully it will resolve your issue will let you know complete details or union and order by statement.

Alias names in union / union all query - SQL Server

I have a simple sql statements as below
CASE 1:
select 1 as a
union
select 2 as a
Output: This case is working as expected
CASE 2:
select 1 as a
union
select 2 as b
Output: Though the alias is 'b' in my second select, it still shows the alias 'a'.
Why cant it take the alias from the second select statement?
How can we make sql to choose the alias from the second select query?
CASE 3:
select 1
union
select 2 as b
Output: Even though my first select statement above does not have any alias name but the second one still have, why the result still shows 'No column name'?
Lets try to teach something useful here. It is not just It's because that's how it is. There is a pattern definition that stipulate the rules for the SQL language and it is called SQL ANSI. You can see a timeline of this definition here: Database Administration - ANSI SQL Standards and Guidelines
The reason behind this definition is simple to understand. Since a UNION operation transform the result of two queries into one, some rules must be applied like the definition of the fields name, the types of the fields (in order they are select) and some others.
The alias part works just for the first one because there is no way for the database to identify which column would be the right one in a union operation as you will get one row per result:
select 1 as a
UNION
select 2
This will result in:
a
1
2
Since it is showed as ROWS how the database would work if it name each column for each SQL in the UNION stack?
-a
1
-b
2
That's why the rule of the first query alias is applied.
The SQL ANSI document is not free although if you dig enough you may find earlier versions of it in PDF. Good luck with that :) (hint: I have an answer in my profile with a working link ;) )
You could wrap everything around a single SELECT and alias that column with what you want.
select a as [b] -- just alias it here with whatever you want
from (
select 1 as a
union
select 2 as b
...) result_set
But as #Will said, it is what it is, can't change that.
OR:
Just make sure that you use the query with the "alias" that you want at the top and UNION that with a single SELECT statement that contains other queries / values you have.
select 2 as b
union
select a
from (
select 1 as a
union
select 3 as c
union
... ) result_set

how to use all columns (*) in select statement from different tables using UNION ALL?

I have 10 tables of which 4 tables have 99 columns and 6 tables have 100 columns. I have to combine using UNION ALL. when executing SQL query getting below error
Msg 205, Level 16, State 1, Line 6
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
I understood the reason of error is for not same number of columns. I tried using NULL as Column100 but still getting same error.
please can anyone suggest me how to use * and UNION ALL in SQL query.
Thanks.
If the extra column happens to be at the beginning or end and the other columns are in exactly the same order, then you can add the column manually:
select t99.*, 't99' as col
from t99
union all
select t100.*
from t100;
But really, is it that hard to list the columns? An explicit column list is much less prone to error. And, it will work regardless of where the 100th column appears.
You can get the list in SQL Server Management Studio by clicking on the table name. You can also run a query such as:
select column_name
from information_schema.columns
where table_name = 't99';
And then use the column names to construct the query (I often use a spreadsheet for this purpose).
UNION requres that columns before and after it MATCH.
You can not do union of 99 columns and then 100 columns. You have to either provide dummy value for 100th column that do not exist in that table, or tell DB to skipp that column.
So add to the smaller table select:
NULL AS missing-column-name
Or list all the common columns by hand omitting columns that do not exists in both.

Query to compare differences of two columns from two different tables

I am attempting to create a UNION ALL query, on two differently named columns in two different tables.
I would like to take the "MTRL" column in the table USER_EXCEL and compare it against the "short_material_number" column from the IM_EXCEL table. I would then like the query to only return the differences between the two columns. Both columns house material numbers but are named differently (column wise) in the tables.
What I have so far is:
(SELECT [MTRL] FROM dbo.USER_EXCEL
EXCEPT
SELECT [short_material_number] FROM dbo.IM_Excel)
UNION ALL
(SELECT [short_material_number] FROM dbo.IM_Excel
EXCEPT
SELECT [MTRL] FROM dbo.USER_EXCEL)
However, when trying to run that query I receive an error message that states:
Msg 8114, Level 16, State 5, Line 22
Error converting data type varchar to float.
You're almost certainly getting this error because one of your two columns is a FLOAT data type, while the other is VARCHAR. This article would be a good place to start reading about implicit conversions, which happen when you try to compare two columns that are of different data types.
To get this working, you need to convert the float to a varchar, like in the example below.
(
SELECT [MTRL] FROM dbo.USER_EXCEL
EXCEPT
SELECT CAST([short_material_number] AS VARCHAR(18)) FROM dbo.IM_Excel
)
UNION ALL
(
SELECT CAST([short_material_number] AS VARCHAR(18)) FROM dbo.IM_Excel
EXCEPT
SELECT [MTRL] FROM dbo.USER_EXCEL
)
From you question I understand you are trying to compare two columns but returning only one column I would recommend you to use following query to compare the differences side by side
SELECT ue.[MTRL], ie.[short_material_number]
FROM dbo.IM_Excel ie
FULL OUTER JOIN
dbo.USER_EXCEL ue
ON CAST(ie.[short_material_number] AS VARCHAR(20)) = ue.[MTRL]
WHERE ie.[short_material_number] IS NULL
OR ue.[MTRL] IS NULL

Resources