Skip to content
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

Query optimization: remove inner join from subquery navigation contains #4389

Open
mikary opened this issue Jan 24, 2016 · 3 comments
Open

Comments

@mikary
Copy link
Contributor

mikary commented Jan 24, 2016

When a sub query uses Contains on a navigation, like the following:

        [ConditionalFact]
        public virtual void Where_subquery_on_navigation()
        {
            using (var context = CreateContext())
            {
                var query = from p in context.Products
                            where p.OrderDetails.Contains(context.OrderDetails.FirstOrDefault(orderDetail => orderDetail.Quantity == 1))
                            select p;

                var result = query.ToList();

                Assert.Equal(1, result.Count);
            }
        }

The SQL contains an inner join on the same table:

SELECT [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[UnitsInStock]
FROM [Products] AS [p]
WHERE (
    SELECT CASE
        WHEN EXISTS (
            SELECT 1
            FROM (
                SELECT [o].[OrderID], [o].[ProductID]
                FROM [Order Details] AS [o]
                WHERE [p].[ProductID] = [o].[ProductID]
            ) AS [t]
            INNER JOIN (
                SELECT TOP(1) [orderDetail].[OrderID], [orderDetail].[ProductID]
                FROM [Order Details] AS [orderDetail]
                WHERE [orderDetail].[Quantity] = 1
            ) AS [t0] ON ([t].[OrderID] = [t0].[OrderID]) AND ([t].[ProductID] = [t0].[ProductID]))
        THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
    END
) = 1

In cases where the Inner Join is on the same table, it may be possible to eliminate the join

SELECT [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[UnitsInStock]
FROM [Products] AS [p]
WHERE (
    SELECT CASE
        WHEN EXISTS (
            SELECT 1
            FROM (
                SELECT TOP(1) [orderDetail].[ProductID]
                FROM [Order Details] AS [orderDetail]
                WHERE [orderDetail].[Quantity] = 1
            ) AS [t]
            WHERE [p].[ProductID] = [t].[ProductID])
        THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
    END
) = 1
@AndriySvyryd
Copy link
Member

@smitpatel Duplicate of #3419?

@smitpatel
Copy link
Contributor

We need to see what is SQL generated in new pipeline.

@AndriySvyryd AndriySvyryd added the verify-fixed This issue is likely fixed in new query pipeline. label Aug 23, 2019
@ajcvickers ajcvickers modified the milestones: Backlog, 3.1.0 Sep 4, 2019
@smitpatel smitpatel self-assigned this Sep 12, 2019
@smitpatel
Copy link
Contributor

The test is blocked on #15260

@smitpatel smitpatel removed the verify-fixed This issue is likely fixed in new query pipeline. label Sep 12, 2019
@smitpatel smitpatel removed their assignment Sep 12, 2019
@smitpatel smitpatel modified the milestones: 3.1.0, Backlog Sep 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants