Sql server 自联接同一字段上的表时丢失联接
我有一个查询,在SQL Server Management Studio中,它看起来像这样:Sql server 自联接同一字段上的表时丢失联接,sql-server,linq,linq-to-entities,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 Ex
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
和Type
匹配的所有记录。到目前为止,一切顺利。然后我需要再次使用vMatrix
连接该结果,这次匹配id
字段以选择vMatrix
中与上次连接的id
匹配的所有记录,然后我只需按类型对其进行过滤
我一直在拼命尝试在LINQ语句中实现这一点,但它不断丢失第二个连接,基本上只返回第一个连接的结果(如果我删除类型
过滤器,否则它什么也不返回)。例如:
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
子句,连接顺序重新排列,等等,所有这些的变化都一致地给了我一个实际的查询,只有一个连接。不知什么原因,它似乎不会在表上进行自联接
我错过了什么
我的猜测是,它正在查看id==id
部分,并决定它可以优化连接,但它不能。生成的SQL基本上与我的SQL语句减去第二个连接相同。没有第二个内部联接
,也没有与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 f in r2.DefaultIfEmpty()
where f.type == filterType
select f.code).Distinct().ToList();
我突然又失去了最后一个连接,结果一无所获。在你的第二个内部连接中,你指的是你之前已经用第一个内部连接操作过的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)
谢谢,但问题不在于SQL本身,我知道如何编写SQL,以获得我想要的结果(参见第一个)。我想弄明白的是如何说服LINQ to实体从LINQ语句生成(或等效)SQL。但出于某种原因,它似乎想忽略第二次加入。