在同一字段上自联接表时丢失连接

时间:2014-08-27 19:20:47

标签: sql-server linq linq-to-entities

我有一个查询,在SQL Server Management Studio中看起来像这样:

SELECT 
    distinct(r2.code) AS code
    FROM  (SELECT 
    vMatrix.type AS type, 
    vMatrix.code AS code, 
    vMatrix.id AS id
    FROM vMatrix AS vMatrix) AS Extent1
    INNER JOIN DE_Scratch AS Extent2 ON (Extent1.code = Extent2.Code) AND (Extent1.type = Extent2.Type)
    INNER JOIN vMatrix as r2 ON Extent1.id = r2.id
    WHERE (Extent2.HeaderID = 94 and r2.type = 4)

基本上我有一个名为vMatrix的表格,我首先将其与另一个名为DE_Scratch的表格一起加入,以选择vMatrix中匹配Code和{{1}的所有记录与Type一起使用。到现在为止还挺好。然后我需要再次将该结果与DE_Scratch相关联,这次匹配vMatrix字段以选择id中与上次加入中的vMatrix匹配的所有记录然后我只是按id过滤它。

我一直在拼命想要在LINQ语句中完成这项工作,但它一直失去第二次连接,基本上只返回第一次连接的结果(如果我删除了type过滤器 - 否则它没有回报)。例如:

type

使用和不使用var stuff = (from r1 in ctx.vMatrices join sr in ctx.DE_Scratch.Where(t => t.HeaderID == header.ID) on new { c = r1.code, t = r1.type } equals new { c = sr.Code, t = sr.Type } join r2 in ctx.vMatrices on r1.id equals r2.id into tmp from t in tmp where t.region_type == filterType select t.code).Distinct().ToList(); 子句以及重新排列连接顺序等的变体都会一直给我一个只有一个连接的实际查询。由于某种未知的原因,它似乎不会在桌面上进行自我加入。

我在这里缺少什么?

我的猜测是,它正在查看into部分,并决定它可以优化加入,但它不能。生成的SQL与我的SQL语句减去第二个连接基本相同。没有第二个id == id且没有与inner join匹配的子句。如何强制它不要忽略该连接?

例如:

id = id

生成这个:

var stuff = (from r2 in ctx.vMatrices
           join r1 in (from t in ctx.vMatrices
                       join sr in ctx.DE_Scratch.Where(t => t.HeaderID == header.ID)
                       on new { c = t.code, t = t.type } equals new { c = Code, t = Type }
                       select t.id)
           on r2.id equals r1 
           select r2).ToList();

更新:这就是我所拥有的:

SELECT 
    [Extent1].[type] AS [type], 
    [Extent1].[code] AS [code], 
    [Extent1].[id] AS [id]
    FROM  (SELECT 
    [vRegionMatrix].[type] AS [type], 
    [vRegionMatrix].[code] AS [code], 
    [vRegionMatrix].[id] AS [id]
    FROM [dbo].[vMatrix] AS [vMatrix]) AS [Extent1]
    INNER JOIN [dbo].[DE_Scratch] AS [Extent2] ON ([Extent1].[type] = [Extent2].[Type]) AND ([Extent1].[code] = [Extent2].[Code])
    WHERE ([Extent2].[HeaderID] = @p__linq__0) AND (@p__linq__0 IS NOT NULL)

几乎有效。问题是,在某些情况下,分组将有多个条目,因此使用var regions = (from r1 in (from t in ctx.vMatrices join sr in ctx.DE_Scratch.Where(t => t.HeaderID == header.ID) on new { c = t.code, t = t.type.Value } equals new { c = sr.Code, t = sr.Type } select t.id) join r2 in ctx.vMatrices.GroupBy(c => c.id) on r1 equals r2.Key select (int?)r2.DefaultIfEmpty().Where(l => l.type == filterType).FirstOrDefault().code).Distinct().ToList(); 我会丢失一些结果。我需要的是等同于FirstOrDefault()以展平群组的结果,但当我尝试删除最后一行并将其替换为另一行SelectMany时:

from...in

我突然失去了最后一次加入而最终没有任何结果。

1 个答案:

答案 0 :(得分:0)

在你的第二个INNER JOIN中你指的是你之前用你的第一个INNER JOIN操纵过的Extend1。您可以尝试类似

的内容
SELECT 
distinct(r2.code) AS code
FROM  ((SELECT 
vMatrix.type AS type, 
vMatrix.code AS code, 
vMatrix.id AS id
FROM vMatrix AS vMatrix) AS Extent1
INNER JOIN DE_Scratch AS Extent2 ON (Extent1.code = Extent2.Code) 
AND (Extent1.type = Extent2.Type)) AS Extend3
INNER JOIN vMatrix as r2 ON Extent3.id = r2.id
WHERE (Extent2.HeaderID = 94 and r2.type = 4)