I have two select statements joined by "union". While executing that statement I've got:
Error report:
SQL Error: ORA-01790: expression must have same datatype as corresponding expression
01790. 00000 - "expression must have same datatype as corresponding expression"
Maybe you can give me an advise on how to diagnose this problem?
Without looking at your SQL, I would guess that you have columns being UNION'ed that have different data types.
Here's what found:
ORA-01790: expression must have same datatype as corresponding expression
Cause: A SELECT list item corresponds to a SELECT list item with a different datatype in another query of the same set expression.
Action: Check that all corresponding SELECT list items have the same datatypes. Use the TO_NUMBER, TO_CHAR, and TO_DATE functions to do explicit data conversions.
I haven't seen your query, but I am guessing that one select in your union is not selecting the same columns as the other.
Clearly the issue for the poster was solved over half a decade ago, nonetheless I wanted to point out to anyone reading this post in search of help that the order of the selected properties (columns) must match from one unioned statement to the next. It is not enough to simply have the names and the data types match, though that is in a sense the root cause. But due to the way the Union statements are handled in Oracle, it is possible to get the ORA-01790 error due to a mismatch in the ordering of columns only.
In my case, I had a query with a UNION ALL of two selects. One select had a column named "generic_column_name" as the 25th item in the select, and the other select had that same column named "generic_column_name" of the very same data type (I tested several ways through hard coding and also using forced data type conversions). However the second select had this item in the 19th place, so all of the columns from there on were offset and this triggered the ORA-01790 error.
As I mention in the question I'd like to have SUGGESTIONS for how to troubleshoot my problem.
What I've done is enabled one column at a time in each select statement and found that I had mismatch at the very last column of my SQL UNION. Thanks a lot for participating and helping me, but I knew I had type mismatch, WHAT I didn't know is how to troubleshoot.
The error is telling you that you're union-ing columns with different datatypes. There are oracle functions that will convert one type to another (e.g. "to_char"), you'll have to convert the datatypes into a common format, or at least one into the other. If you post the actual query/types it'd be possible to be more specifc.
You need to make sure that corresponding columns in your union have the same data type. The easiest way would be to comment out columns one by one to narrow down to the column and then use explicit type conversion function in one of them to make types match.
You tried to execute a SELECT statement (probably a UNION or a UNION ALL), and all of the queries did not contain matching data types in the result columns.
Techonthenet - ORA-01790
I had the same problem today. The issue is in the union, basically in the order of the columns
Related
I am trying to insert data from a staging table into the master table. The table has nearly 300 columns, and is a mix of data-typed Varchars, Integers, Decimals, Dates, etc.
Snowflake gives the unhelpful error message of "Numeric value '' is not recognized"
I have gone through and cut out various parts of the query to try and isolate where it is coming from. After several hours and cutting every column, it is still happening.
Does anyone know of a Snowflake diagnostic query (like Redshift has) which can tell me a specific column where the issue is occurring?
Unfortunately not at the point you're at. If you went back to the COPY INTO that loaded the data, you'd be able to use VALIDATE() function to get better information to the record and byte-offset level.
I would query your staging table for just the numeric fields and look for blanks, or you can wrap all of your fields destined for numeric fields with try_to_number() functions. A bit tedious, but might not be too bad if you don't have a lot of numbers.
https://docs.snowflake.com/en/sql-reference/functions/try_to_decimal.html
As a note, when you stage, you should try and use the NULL_IF options to get rid of bad characters and/or try to load them into stage using the actual datatypes in your stage table, so you can leverage the VALIDATE() function to make sure the data types are correct before loading into Snowflake.
Query your staging using try_to_number() and/or try_to_decimal() for number and decimal fields of the table and the use the minus to get the difference
Select $1,$2,...$300 from #stage
minus
Select $1,try_to_number($2)...$300 from#stage
If any number field has a string that cannot be converted then it will be null and then minus should return those rows which have a problem..Once you get the rows then try to analyze the columns in the result set for errors.
If I perform an SQL UNION on 2 tables, what are the explicit conditions that UNION uses to decide that any 2 rows are the same?
Looking through the Postgres documentation, it just states "A row is in the set union of two result sets if [it] appears in at least one of the result sets". If [WHAT] appears in the result sets?
Does it match column1, then column2, ...? How does it decide to stop at columnX?
I'm a little stunned that the actual matching rules aren't spelled out explicitly. Or, I just couldn't find them with 10 minutes of Google-ing.
Thanks for your help.
UNION (as compared to UNION ALL) is similar to DISTINCT in that for duplicates to be removed, all columns have to be identical.
I'm not sure what you are asking, but perhaps this is it.
When you use union (or other set operators) on two tables, the rows are compared by position. All columns must match -- that is, there need to be the same number of columns in both tables. Postgres will decide on the type of each column in the result set based on type precedence rules. The columns in either table will be converted to the specified type.
Does that address what you are asking?
Actually, this is pretty much specified in the documentation:
SQL UNION constructs must match up possibly dissimilar types to become
a single result set. The resolution algorithm is applied separately to
each output column of a union query. The INTERSECT and EXCEPT
constructs resolve dissimilar types in the same way as UNION. The
CASE, ARRAY, VALUES, GREATEST and LEAST constructs use the identical
algorithm to match up their component expressions and select a result
data type.
Type Resolution for UNION, CASE, and Related Constructs
If all inputs are of the same type, and it is not unknown, resolve as
that type.
If any input is of a domain type, treat it as being of the domain's
base type for all subsequent steps. [9]
If all inputs are of type unknown, resolve as type text (the preferred
type of the string category). Otherwise, unknown inputs are ignored
for the purposes of the remaining rules.
If the non-unknown inputs are not all of the same type category, fail.
Choose the first non-unknown input type which is a preferred type in
that category, if there is one.
Otherwise, choose the last non-unknown input type that allows all the
preceding non-unknown inputs to be implicitly converted to it. (There
always is such a type, since at least the first type in the list must
satisfy this condition.)
Convert all inputs to the selected type. Fail if there is not a
conversion from a given input to the selected type.
I want to sort my column numbers at report level in SSRS instead of my query as I have some other columns sorted at query level and doing both sorts at query level don't work well. At the moment I get Columns order like 1, 10,2,3,4,5,6 instead of 1,2,3,4,5,6...10.
Once sorting is done I also want to add 'sales_' to the column name so I see sales_1, sales_2, sales_3 and so on. I understand this could be pretty straightforward but I'm new to SSRS. Thanks in advance.
The sort you are describing (1, 10,2,3,4) is a string sort, you need to convert the data type on that column to a numeric (in this case integer) type so that the sort is correct.
There are two solutions to this, you can add a calculated field to the record set, this can be helpful if you need to use this column multiple times, or you can simply use an expression for the sort order.
Right click on your dataset and select Add Calculated field, a dialog will open with all the column definitions for the query, here you can add your own custom fields.
For a custom field you will need an expression, which was the other options originally, so lets have a look at that component.
Edit the sort definition for the Tablix or group and select the field you want to sort on, to sort the way you would like the value needs to be numeric, we can use the CInt function to convert a value to an integer
NOTE: when using expressions to convert data types, if your data might not be convertible you may need to validate the value before conversion otherwise your
report execution will fail. The error messages are pretty helpful though and the expression dialog shows available functions an examples of usage for each of them.
For your second issue, use an expression in the field where you are displaying the data to concatenate the values, you can use the String.Format function or you can use simple string addition:
Expression Examples:
="sales_" + Fields!ItemValue.Value
="sales_" & Fields!ItemValue.Value
=String.Format("sales_{0}", Fields!ItemValue.Value)
I hope this helps you on your way, welcome to SSRS!
I am having to create a second header line and am using the first record of the Query to do this. I am using a UNION All to create this header record and the second part of the UNION to extract the Data required.
I have one issue on one column.
,'Active Energy kWh'
UNION ALL
,SUM(cast(invc.UNITS as Decimal (15,0)))
Each side are 11 lines before and after the Union and I have tried all sorts of combinations but it always results in an error message.
The above gives me "Error converting data type varchar to numeric."
Any help would be much appreciated.
The error message indicates that one of your values in the INVC table UNITS column is non-numeric. I would hazard a guess that it's either a string (VARCHAR or similar) column or something else - and one of the values has ended up in a state where it cannot be parsed.
Unfortunately there is no way other than checking small ranges of the table to gradually locate the 'bad' row (i.e. Try running the query for a few million rows at a time, then reducing the number until you home in on the bad data). SQL 2014 if you can get a database restored to it has the TRY_CONVERT function which will permit conversions to fail, enabling a more direct check - but you'll need to play with this on another system
(I'm assuming that an upgrade to 2014 for this feature is out of the question - your best bet is likely just looking for the bad row).
The problem is that you are trying to mix header information with data information in a single query.
Obviously, all your header columns will be strings. But not all your data columns will be strings, and SQL Server is unhappy when you mix data types this way.
What you are doing is equivalent to this:
select 'header1' as col1 -- string
union all
select 123.5 -- decimal
The above query produces the following error:
Error converting data type varchar to numeric.
...which makes sense, because you are trying to mix both a string (the header) with a decimal field.
So you have 2 options:
Remove the header columns from your query, and deal with header information outside your query.
Accept the fact that you'll need to convert the data type of every column to a string type. So when you have numeric data, you'll need to cast the column to varchar(n) explicitly.
In your case, it would mean adding the cast like this:
,'Active Energy kWh'
UNION ALL
,CAST(SUM(cast(invc.UNITS as Decimal (15,0))) AS VARCHAR(50)) -- Change 50 to appropriate value for your case
EDIT: Based on comment feedback, changed the cast to varchar to have an explicit length (varchar(n)) to avoid relying on the default length, which may or may not be long enough. OP knows the data, so OP needs to pick the right length.
In my SQL, I would need to compare data between two tables in SQLServer 2008R2 to return the rows where mismatch is present (using EXCEPT) and likewise matching rows in other cases (INTERSECT). The problem is, some of the columns have NTEXT datatype (SQLServer), and SQLServer gives error when such tables having columns with NTEXT are present.
Example:
SELECT * FROM table_pre
EXCEPT
SELECT * FROM table_post
The above operation gives an error -
'The ntext data type cannot be selected as DISTINCT because it is not comparable.'
I believe that tables (table_pre, table_post) have at least one column of datatype = NTEXT that is causing the comparison to fail.
Question -
1. Is there some way to exclude these NTEXT columns from the above comparison, without me having to explicitly list out the column names and excluding the problem column? There's a large number of columns involved and explicitly listing is not easy.
2. Can I just explicitly cast/convert the NTEXT column alone to say VARCHAR, and still go by not having to list down the rest of the columns?
3. Or, in general, can I somehow exclude certain columns by listing those out during such comparisons?
Any suggestions, really appreciated! Thanks.
Question - 1. Is there some way to exclude these NTEXT columns from the above comparison,
Yes, use explicitly the column names.
without me having to explicitly list out the column names and excluding the problem column?
Using * is a bad habit, you well deserve the error for abusing it.
There's a large number of columns involved and explicitly listing is not easy
Is actually trivial, build the statement dinamycally
Can I just explicitly cast/convert the NTEXT column alone to say VARCHAR
No. You have to convert to NVARCHAR, the N is very important. But, yes you can convert.
Or, in general, can I somehow exclude certain columns by listing those out during such comparisons
Fortunately no. SQL does not randomly decide what columns are or are not part of a result, so you get the predictability you desire.
So, in conclussion:
never use *
build complex statements dynamically. SELECT ... FROM sys.columns is your friend, you can easily build it in a few seconds
ditch the deprecated TEXT, NTEXT and IMAGE types