-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Set operations: pushdown Take without Offset/OrderBy for SqlServer #16238
Comments
You can also consider a translation like select 1 as x, null as __throwaway__
union
select 2, null
order by 2
offset 0 rows
fetch next 1 rows only Which requires no extra subquery. But we'd have to add a dummy constant to both sides of the union. Sql server will realize the constant is the same on both sides and throw it away, and produce the exact same plan. (it will still appear in the output list but that can just be ignored when materializing the results.) |
Nice trick with ordering by a null constant - there are also other ways to get random ordering in databases without dummy projections. We should actually do some quick measurement to see which technique is best (the subquery may actually work better than the extra order by). On an unrelated note, the set operation already generates null constants for situations where two different entity types are used as operands, and not all properties are shared by both sides. |
The order by constant gets eliminated if it's the same constant in both tables. Unfortunately, using That said, Sql server rarely works on the Principle of least astonishment. exec sp_executeSQL N'
select 1 x,null as __throwaway__
union
select 2, null as __throwaway__
order by 2
offset @a row
fetch next @b row only',N'@a int,@b int',0,1 Returns 1 row. exec sp_executeSQL N'
select x
from (
select 1 x,null as __throwaway__
union
select 2, null as __throwaway__
order by 2
offset @a row
fetch next @b row only
) z',N'@a int,@b int',0,1 returns 2 rows. Wrapping the expression to eliminate the extra throwaway column causes sql server to treat the https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=330793a28bdf2eafff46d140fa655a5a |
Note: this is relevant only after #16244 is done.
Take without Offset+OrderBy is usually translated as TOP(n) for SqlServer, but that isn't possible directly on set operations. We need to push the set operation down into a subquery to apply TOP(n) outside. This depends on provider-specific customization of SelectExpression logic.
On Sqlite and PostgreSQL there's no problem with adding LIMIT 1 directly on the set operation (
SELECT 1 AS x UNION SELECT 2 LIMIT 1
).The text was updated successfully, but these errors were encountered: