On Monday, 18 November, 2019 15:01, Jose Isaias Cabrera <jic...@outlook.com> wrote:
>Keith Medcalf, on Monday, November 18, 2019 04:27 PM, wrote... >> >> This relies on two implementation details particular to SQLite3 which >> hold at present, but may of course change at any time: >> (1) that selecting a non-aggregate scalar column will return a value >> from (one of) the row(s) matching the value of the aggregate (most >> RDBMS used to do this, most now throw an error at this construct); and, >> (2) that the optimizer will not optimize "IfNull('p006', max(idate))" >> into 'p006' since the result must always be 'p006' which would of >> course render the select to be a simple select and not an aggregate >> causing "all hell to break loose". >Thanks Keith. So, you are saying that this is a bad INSERT, and I don't >know much to argue, but is working. If I take out the first IfNull, and >there is not, at least one instance of 'p006' in the table, the INSERT >never works. I was thinking of using COALESCE, but that would also mean >that one or the other would have to be not null. Any suggestion would be >appreciated. No, what I am saying is that this particular insert is working with the current version of SQLite3 and is unlikely to work with any other RDBMS that uses SQL as this is using an "implementation detail" specific to SQLite3 that does not exist elsewhere; and, secondly that the particular construction used putting the aggregate function in the second argument of a coalesce where the first argument is a constant is dependent on the query optimizer not "optimizing way" the entire expression based on the fact that the first argument is a not-null constant (though if this optimized away the aggregate-ness of the query this would be a bug in the optimizer, since the optimization process should not cause different results to occur). What I am saying is that you need to be aware of this and if you change versions of SQLite3 then you need to make sure that this query still operates as you intend it to operate. So far as I know the first constraint (the scalar use of columns that are not part of the group by clause in a query) is unlikely to change because this is a significant change to backwards compatibility and Richard is unlikely to make such a change without warnings in second coming type. The second is unlikely with SQLite3 because the optimizer is not based on a query re-write which would be more prone to this sort of issue. The second issue can be bypassed entirely by using bound parameters (since there is no way except by examining the bound parameter at execution time to know that a bound parameter is not NULL) thus precluding the possibility of optimizing away the aggregate function. As in: select ifnull(:a, max(idate)), ifnull(b, 1), ifnull(c, 2), :y, ifnull(e, 4), :idate from t where a == :a and binding values for :a, :y and :idate. There is no way to know at prepare time that parameter :a cannot be null so therefore the ifnull(:a... and the evaluation of the aggregate cannot be optimized away. >[clip] > >> >SELECT IfNull('p006', Max(idate)), >> > IfNull(b, 1), >> > IfNull(c, 2), >> > 'y', >> > IfNull(e, 4), >> > '2019-20-12' >> > FROM t >> > WHERE a = 'p006'; >> > -- The fact that there's a Highway to Hell but only a Stairway to Heaven says a lot about anticipated traffic volume. _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users