使用内部联接和2个左联接的SQL到Linq转换(使用子查询)

时间:2009-11-20 00:01:03

标签: linq-to-sql join subquery left-join

我有以下查询在SSMS中正常工作。我使用LinqPad( C#),但在LinqToSql中使用左外连接成功真是令人费解:

SELECT DISTINCT 
  A.LocID, 
  V1.PrfValue AS pID, 
  V2.PrfValue AS sID,
  D.DivisionManager, 
  A.IsApproved, 
  A.DateCreated
FROM         
  dbo.Locations AS A 
INNER JOIN
  dbo.Divisions AS D 
  ON    A.DivisionID = D.DivisionID 
LEFT OUTER JOIN
  dbo.ValuesInLocations AS V1 
  ON    A.LocID = V1.LocID 
    AND 
    V1.PrfID IN (SELECT 
            PrfID 
                 FROM 
            dbo.PrfTag 
             WHERE 
            (LevelTypeID = 1)) 
LEFT OUTER JOIN
   dbo.ValuesInLocations AS V2 
   ON   A.LocID = V2.LocID 
    AND 
    V2.PrfID IN (SELECT 
            PrfID 
             FROM 
            dbo.PrfTag 
             WHERE 
            (LevelTypeID = 2))

正如您所看到的,这不是开始工作的最优雅的查询,我同意左边连接中的子查询可以得到改进。但是,请你帮我翻译一下吗?

2 个答案:

答案 0 :(得分:1)

以下是您的查询的2种可能的翻译。我在第一个翻译中使用了3个单独的查询,以使其更具可读性。我希望你发现它们很有用。

var query1 =
    from prfTag in DataContext.PrfTag
    where prfTag.LevelTypeID = 1
    select PrfID;

var query1 =
    from prfTag in DataContext.PrfTag
    where prfTag.LevelTypeID = 2
    select PrfID;

var query = (
from A in DataContext.Locations
join D in DataContext.Divisions
    on A.DivisionID equals D.DivisionID
join V1 in DataContext.ValueInLocations
    on A.LocID equals V1.LocID
    into VGroup1
from V1 in VGroup1.DefaultIfEmpty()
join V2 in DataContext.ValueInLocations
    on A.LocID equals V2.LocID
    into VGroup2
from V2 in VGroup2.DefaultIfEmpty()
where (V1 == null || (V1 != null && query1.Contains(V1.PrfID)))
    && (V2 == null || (V2 != null && query2.Contains(V2.PrfID)))
select new
{
    A.LocID,
    pID = V1 != null ? V1.PrfValue : "",
    sID = V2 != null ? V2.PrfValue : "",
    D.DivisionManager,
    A.IsApproved,
    A.DateCreated
}).Distinct();

这是第二种可能的翻译:

var query = (
from A in DataContext.Locations
join D in DataContext.Divisions
    on A.DivisionID equals D.DivisionID
join V1 in DataContext.ValueInLocations
    on A.LocID equals V1.LocID
    into VGroup1
from V1 in VGroup1.DefaultIfEmpty()
join prfTag1 in DataContext.PrfTag
    on V1.PrfID equals prfTag1.PrfID
join V2 in DataContext.ValueInLocations
    on A.LocID equals V2.LocID
    into VGroup2
from V2 in VGroup2.DefaultIfEmpty()
join prfTag2 in DataContext.PrfTag
    on V2.PrfID equals prfTag2.PrfID
select new
{
    A.LocID,
    pID = V1 != null ? V1.PrfValue : "",
    sID = V2 != null ? V2.PrfValue : "",
    D.DivisionManager,
    A.IsApproved,
    A.DateCreated
}).Distinct();

答案 1 :(得分:0)

在LINQ中可能有一些棘手的方法可以做到这一点,但LINQ JOIN对于内连接以外的任何事情都很痛苦。为了可维护性,我不鼓励使用linq进行此查询。我知道这并没有完全回答你的问题,但我认为你不会得到你喜欢的答案,这比那个问题更好。