If you have a table with a varchar column containing different kinds of values (int, date, string, float) all converted to a string and you then want to join the int value to a different table. I'm getting errors like "Cannot convert "some date value" to a numeric". Setup the tables:
The result I am looking for:
The queries: SQL 1:
SQL 2:
SQL 3:
SQL 4:
Result 1, 2, 3 and 4:
SQL 5:
Result 5: This doesn't crash but it doesn't give the result I am looking for (as expected because IsDate('1') returns true) My questions:
Extra note: In the actual case I'm using this for I could really use the available PK/FK indexes for performance reasons and I would rather not create additional indexes like "cast(JoinId.Id as varchar)" as suggested in Volkers answer. Tested with ASA 16.0.0.2283 |
What version do you use? With 12.0.1.4403, all 5 queries do succeed and do return the desired result (although queries 2 and 3 look similar to me...). That being said, in general when the query engine seems to try to do undesired casts and fails, I'd usually try to adapt the "comparison goal" accordingly, such as select * from TestData left outer join JoinId on TestData.Fieldname = 'Id' and cast(JoinId.Id as varchar) = TestData.TestData That would even work if you would attempt to join over a different row that has no int value, such as TestData.Fieldname = 'Date'. Tested with ASA 16.0.0.2283 I should have added that in the actual case I'm using this for I could really use indexes for performance reasons and I would rather not create an index on "cast(JoinId.Id as varchar)".
(11 Jul '16, 04:15)
Christian Ha...
Replies hidden
Ah, I see, with 16.0.0.2270 I do the errors for queries 1-4, too. However, for me query 5 the result seems fitting. Here's another attempt by building a derived query just with the "comparable rows" and then join that with JoinId. That may or may not help in your real case, that's difficult to tell without knowing that case... select TestData., JoinId. from TestData left join (select * from TestData where Fieldname = 'Id') TestDataWithId on TestData.FieldName = TestDataWithId.FieldName left outer join JoinId on TestDataWithId.TestData = JoinId.Id
(11 Jul '16, 04:55)
Volker Barth
In the result for query 5 I get the "Id" column contains only "NULL" values. Where I need a value "1" in that column for the record with "FieldName" = "Id". Your attempt looks promising. I would need to see if that leads to acceptable results (if it's not too slow) However I hope that someone from SAP will react on this, and explain what is happening here and why this seems to work with version 12 and not with 16.
(11 Jul '16, 05:47)
Christian Ha...
Replies hidden
FWIW, with 16.0.0.2270, query 5 returns the desired result set for me:
(11 Jul '16, 05:59)
Volker Barth
Thats strange... In that first row I'm getting Id = NULL If I try
The result is
Then I'm guessing IsDate('1') is returning 0 for you?
(11 Jul '16, 06:35)
Christian Ha...
Yes, I'm getting
here. Note, I'm running with German locale but with default date_format = 'YYYY-MM-DD' and default date_order = 'YMD'. According, the following cast fails with SQLCODE -157:
So that difference seems to explain the different query results...
(11 Jul '16, 06:52)
Volker Barth
I'm indeed running with different settings: date_format = 'DD-MM-YYYY' and date_order = 'DMY'. The result for cast('1' as date) then is '01-07-2016'. If I change them back to the default, I get the same results as you.
(11 Jul '16, 07:42)
Christian Ha...
This also means that if i choose 10 as the value for TestData in the first row we would have seen the same behaviour (1-1-1000 vs 10-07-2016)
(11 Jul '16, 07:49)
Christian Ha...
|
While a little late to the thread . . . A simpler rewrite might be this one:
The CASTing (or alternatively a Convert()) of JoinId.Id to a character string avoids the implicit/automatic conversion that is exposing this issue. I'm assuming 12.0.x did something similar when evaluating the original predicate. Both types of automatic conversion are feasible here, ie:
and since this predicate 'could operate' either way (as a numeric comparison or a character comparison) there seems to be no preferred bias to either. I'm not quite certain if this is exactly a bug or not. Treating all such comparisons as numeric comparisons whenever possible/feasible can be significantly more efficient than assuming every such expression to be a character string comparison. Yes, the explicit cast in the JOIN condition is probably the simplest rewrite, see the suggestion in my answer... However, as Christian has stated, the cast may prevent the usage of an index on the according column JoinId.Id here, right?
(12 Jul '16, 02:36)
Volker Barth
|