linq - 使用 LINQ 在子查询中高级多重联接

标签 linq join subquery coalesce

我花了一个下午的时间试图思考如何将以下查询转换为 LINQ,但我不太明白。

declare @productId int; set @productId = 3212;

select * from InformationData data where productId = @productId and orgId = 1
and exists(
    select id from (
        select coalesce(id1.id, id2.id, id3.id) as id from (
            select productId,attributeId from InformationData where productId = @productId group by productId,attributeId
        ) id
        left outer join InformationData id1 on id1.productId = id.productId and id1.attributeId = id.attributeId and id1.language = 1
        left outer join InformationData id2 on id2.productId = id.productId and id2.attributeId = id.attributeId and id2.language = 2
        left outer join InformationData id3 on id3.productId = id.productId and id3.attributeId = id.attributeId and id3.language = 0
    ) row
    where row.id = data.id
)

该查询的目的是使用 2 种后备语言从表中获取数据,因此如果数据不存在于语言 1 中,则使用语言 2 获取数据,如果数据 2 不存在,则使用语言 0 获取数据这是全局翻译。

我可以获得大部分正确的内部查询(除了 id1.language = 1,我似乎无法让它加入我要加入的表的成员,有什么想法吗?)

这是我的代码(LINQPad 代码):

(
    from data in (
        from d in InformationData where d.ProductId == 3212 group d by new { d.ProductId, d.AttributeId } into p select new { ProductId = p.Key.ProductId, AttributeId = p.Key.AttributeId }
    )
    join x1 in InformationData on new { a = data.ProductId, b = data.AttributeId } equals new { a = x1.ProductId, b = x1.AttributeId } into f1
        from r1 in f1.DefaultIfEmpty()
        where r1.Language == 1
    join x2 in InformationData on new { a = data.ProductId, b = data.AttributeId } equals new { a = x2.ProductId, b = x2.AttributeId } into f2
        from r2 in f2.DefaultIfEmpty()
        where r2.Language == 2
    join x3 in InformationData on new { a = data.ProductId, b = data.AttributeId } equals new { a = x3.ProductId, b = x3.AttributeId } into f3
        from r3 in f3.DefaultIfEmpty()
        where r3.Language == 2
    select new { Id = ((int?)r1.Id) ?? ((int?)r2.Id) ?? r3.Id }
).Dump();

生成以下 SQL:

-- Region Parameters
DECLARE @p0 Int SET @p0 = 3212
DECLARE @p1 Int SET @p1 = 2
DECLARE @p2 Int SET @p2 = 2
DECLARE @p3 Int SET @p3 = 1
-- EndRegion
SELECT COALESCE([t2].[id],COALESCE([t3].[id],[t4].[id])) AS [Id]
FROM (
    SELECT [t0].[productId], [t0].[attributeId]
    FROM [InformationData] AS [t0]
    WHERE [t0].[productId] = @p0
    GROUP BY [t0].[productId], [t0].[attributeId]
    ) AS [t1]
LEFT OUTER JOIN [InformationData] AS [t2] ON ([t1].[productId] = [t2].[productId]) AND ([t1].[attributeId] = [t2].[attributeId])
LEFT OUTER JOIN [InformationData] AS [t3] ON ([t1].[productId] = [t3].[productId]) AND ([t1].[attributeId] = [t3].[attributeId])
LEFT OUTER JOIN [InformationData] AS [t4] ON ([t1].[productId] = [t4].[productId]) AND ([t1].[attributeId] = [t4].[attributeId])
WHERE ([t4].[language] = @p1) AND ([t3].[language] = @p2) AND ([t2].[language] = @p3)

但我无法将其与查询的其余部分放在一起,也许我只是累了,我一直让它做很多交叉应用。有人有什么建议吗?

最佳答案

经过一夜好眠,一些重要的事情变得更加明亮,我找到了解决方案:)对于任何对此感到好奇的人来说,这就是


(
    from i in InformationData
    where (
        from data in (
            from d in InformationData where d.ProductId == 3212 group d by new { d.ProductId, d.AttributeId } into p select new { ProductId = p.Key.ProductId, AttributeId = p.Key.AttributeId }
        )
        join x1 in InformationData on new { a = data.ProductId, b = data.AttributeId, c = 1} equals new { a = x1.ProductId, b = x1.AttributeId, c = x1.Language } into f1
            from r1 in f1.DefaultIfEmpty()
        join x2 in InformationData on new { a = data.ProductId, b = data.AttributeId, c = 2 } equals new { a = x2.ProductId, b = x2.AttributeId, c = x2.Language } into f2
            from r2 in f2.DefaultIfEmpty()
        join x3 in InformationData on new { a = data.ProductId, b = data.AttributeId, c = 0 } equals new { a = x3.ProductId, b = x3.AttributeId, c = x3.Language } into f3
            from r3 in f3.DefaultIfEmpty()
        select new { Id = ((int?)r1.Id) ?? ((int?)r2.Id) ?? r3.Id }
    ).Any(d => d.Id == i.Id)
    select i
).Dump();

这是生成的 SQL


-- Region Parameters
DECLARE @p0 Int SET @p0 = 3212
DECLARE @p1 Int SET @p1 = 1
DECLARE @p2 Int SET @p2 = 2
DECLARE @p3 Int SET @p3 = 0
-- EndRegion
SELECT [t0].[id] AS [Id], [t0].[attributeId] AS [AttributeId], [t0].[productId] AS [ProductId], [t0].[value] AS [Value], [t0].[orgId] AS [OrgId], [t0].[version] AS [Version], [t0].[language] AS [Language], [t0].[metaType] AS [MetaType], [t0].[overload] AS [Overload], [t0].[parentId] AS [ParentId]
FROM [InformationData] AS [t0]
WHERE EXISTS(
    SELECT NULL AS [EMPTY]
    FROM (
        SELECT COALESCE([t3].[id],COALESCE([t4].[id],[t5].[id])) AS [value]
        FROM (
            SELECT [t1].[productId], [t1].[attributeId]
            FROM [InformationData] AS [t1]
            WHERE [t1].[productId] = @p0
            GROUP BY [t1].[productId], [t1].[attributeId]
            ) AS [t2]
        LEFT OUTER JOIN [InformationData] AS [t3] ON ([t2].[productId] = [t3].[productId]) AND ([t2].[attributeId] = [t3].[attributeId]) AND (@p1 = [t3].[language])
        LEFT OUTER JOIN [InformationData] AS [t4] ON ([t2].[productId] = [t4].[productId]) AND ([t2].[attributeId] = [t4].[attributeId]) AND (@p2 = [t4].[language])
        LEFT OUTER JOIN [InformationData] AS [t5] ON ([t2].[productId] = [t5].[productId]) AND ([t2].[attributeId] = [t5].[attributeId]) AND (@p3 = [t5].[language])
        ) AS [t6]
    WHERE [t6].[value] = [t0].[id]
    )

关于linq - 使用 LINQ 在子查询中高级多重联接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/835836/

相关文章:

c# - 使用扩展方法的 Entity Framework 分页很慢?

c# - 在 Entity Framework 中动态添加 where 子句

SQL:获取连续值的所有变化点

mysql - 在连接条件中添加通配符

mysql - 子查询返回多于1行的解决方案for update query using select statement

mysql - 子查询。获取每个用户的附加条件

c# - 委托(delegate)和 Func Cast 问题

c# - 我想检查 IEnumerable 的计数,但效率很低

mysql - MySQL 中的分层数据

mysql - 获取每组最高/最小 <whatever> 的记录