복붙노트

[SQL] SQL에 LINQ - 왼쪽 외부 복수로 가입 조건 가입

SQL

SQL에 LINQ - 왼쪽 외부 복수로 가입 조건 가입

내가 LINQ로 번역하려고 다음과 같은 SQL을 가지고 :

SELECT f.value
FROM period as p 
LEFT OUTER JOIN facts AS f ON p.id = f.periodid AND f.otherid = 17
WHERE p.companyid = 100

나는 (x.DefaultIfEmpty (등)에 Y에서 X로 즉.) 왼쪽 외부의 전형적인 구현에 참여 볼 수 있지만 다른 조인 조건 (AND f.otherid = 17) 소개하는 방법이 확실하지 않은

편집하다

왜의 AND f.otherid = 17 조건 부분은 WHERE 절에 대신 가입한다? F 때문에 일부 행을 위해 존재하고 나는 여전히 이러한 행을 포함 할 수 없습니다. 조건이 WHERE 절에 적용되는 경우는 가입 후 - 다음 내가 원하는 행동을하지 않습니다.

불행하게도이 :

from p in context.Periods
join f in context.Facts on p.id equals f.periodid into fg
from fgi in fg.DefaultIfEmpty()
where p.companyid == 100 && fgi.otherid == 17
select f.value

이 동등 것 같다 :

SELECT f.value
FROM period as p 
LEFT OUTER JOIN facts AS f ON p.id = f.periodid 
WHERE p.companyid = 100 AND f.otherid = 17

어떤 난 후 꽤 것입니다.

해결법

  1. ==============================

    1.당신은 DefaultIfEmpty를 호출하기 전에 조인 조건을 소개합니다 (). 난 그냥 확장 메서드 구문을 사용합니다 :

    당신은 DefaultIfEmpty를 호출하기 전에 조인 조건을 소개합니다 (). 난 그냥 확장 메서드 구문을 사용합니다 :

    from p in context.Periods
    join f in context.Facts on p.id equals f.periodid into fg
    from fgi in fg.Where(f => f.otherid == 17).DefaultIfEmpty()
    where p.companyid == 100
    select f.value
    

    또는 당신은 하위 쿼리를 사용할 수 있습니다 :

    from p in context.Periods
    join f in context.Facts on p.id equals f.periodid into fg
    from fgi in (from f in fg
                 where f.otherid == 17
                 select f).DefaultIfEmpty()
    where p.companyid == 100
    select f.value
    
  2. ==============================

    2.이 역시 작동합니다 ... 당신이있는 경우 여러 열 조인

    이 역시 작동합니다 ... 당신이있는 경우 여러 열 조인

    from p in context.Periods
    join f in context.Facts 
    on new {
        id = p.periodid,
        p.otherid
    } equals new {
        f.id,
        f.otherid
    } into fg
    from fgi in fg.DefaultIfEmpty()
    where p.companyid == 100
    select f.value
    
  3. ==============================

    3.나는이 그렇게하는 방법이 될 것이다는 "조금 늦게"입니다하지만 단지의 경우 사람의 요구 (나는 처음에이 게시물을 찾을 이유입니다) LINQ 방법 구문에서이 작업을 수행 할 수 있는지 알고 :

    나는이 그렇게하는 방법이 될 것이다는 "조금 늦게"입니다하지만 단지의 경우 사람의 요구 (나는 처음에이 게시물을 찾을 이유입니다) LINQ 방법 구문에서이 작업을 수행 할 수 있는지 알고 :

    var results = context.Periods
        .GroupJoin(
            context.Facts,
            period => period.id,
            fk => fk.periodid,
            (period, fact) => fact.Where(f => f.otherid == 17)
                                  .Select(fact.Value)
                                  .DefaultIfEmpty()
        )
        .Where(period.companyid==100)
        .SelectMany(fact=>fact).ToList();
    
  4. ==============================

    4.다음과 같이 또 다른 유효한 옵션은 여러 LINQ 절에 걸쳐 조인 확산하는 것입니다 :

    다음과 같이 또 다른 유효한 옵션은 여러 LINQ 절에 걸쳐 조인 확산하는 것입니다 :

    public static IEnumerable<Announcementboard> GetSiteContent(string pageName, DateTime date)
    {
        IEnumerable<Announcementboard> content = null;
        IEnumerable<Announcementboard> addMoreContent = null;
            try
            {
                content = from c in DB.Announcementboards
                  // Can be displayed beginning on this date
                  where c.Displayondate > date.AddDays(-1)
                  // Doesn't Expire or Expires at future date
                  && (c.Displaythrudate == null || c.Displaythrudate > date)
                  // Content is NOT draft, and IS published
                  && c.Isdraft == "N" && c.Publishedon != null
                  orderby c.Sortorder ascending, c.Heading ascending
                  select c;
    
                // Get the content specific to page names
                if (!string.IsNullOrEmpty(pageName))
                {
                  addMoreContent = from c in content
                      join p in DB.Announceonpages on c.Announcementid equals p.Announcementid
                      join s in DB.Apppagenames on p.Apppagenameid equals s.Apppagenameid
                      where s.Apppageref.ToLower() == pageName.ToLower()
                      select c;
                }
    
                // Add the specified content using UNION
                content = content.Union(addMoreContent);
    
                // Exclude the duplicates using DISTINCT
                content = content.Distinct();
    
                return content;
            }
        catch (MyLovelyException ex)
        {
            // Add your exception handling here
            throw ex;
        }
    }
    
  5. ==============================

    5.복합 키에 가입하여 작성 할 수 있습니다. LINQ가 같이 쓸 수있다 좌우 양측에서 속성을 선택이 필요가있다 또한 경우

    복합 키에 가입하여 작성 할 수 있습니다. LINQ가 같이 쓸 수있다 좌우 양측에서 속성을 선택이 필요가있다 또한 경우

    var result = context.Periods
        .Where(p => p.companyid == 100)
        .GroupJoin(
            context.Facts,
            p => new {p.id, otherid = 17},
            f => new {id = f.periodid, f.otherid},
            (p, f) => new {p, f})
        .SelectMany(
            pf => pf.f.DefaultIfEmpty(),
            (pf, f) => new MyJoinEntity
            {
                Id = pf.p.id,
                Value = f.value,
                // and so on...
            });
    
  6. ==============================

    6.번역하기 전에 당신의 SQL 코드에 약간의 재 작성을 고려의 값이 날 것으로 보인다.

    번역하기 전에 당신의 SQL 코드에 약간의 재 작성을 고려의 값이 날 것으로 보인다.

    (나는 완전히 널 (null)을 피할 것 있지만!) 개인적으로는 노동 조합으로 이러한 쿼리를 써서 :

    SELECT f.value
      FROM period as p JOIN facts AS f ON p.id = f.periodid
    WHERE p.companyid = 100
          AND f.otherid = 17
    UNION
    SELECT NULL AS value
      FROM period as p
    WHERE p.companyid = 100
          AND NOT EXISTS ( 
                          SELECT * 
                            FROM facts AS f
                           WHERE p.id = f.periodid
                                 AND f.otherid = 17
                         );
    

    내가 추측 그래서 (자신의 코드는 질문에 관련이없는 것 같습니다하지만) 나는 MAbraham1의 대답 @의 정신에 동의합니다.

    실제로 중복 널 (null) - 그러나, 쿼리가 명시 적으로 중복 행을 포함하는 단일 열 결과를 생산하도록 설계되어 보인다! 그것은이 방법은 결함이 있다는 결론에 도달하기 어렵지 않다.

  7. from https://stackoverflow.com/questions/1122942/linq-to-sql-left-outer-join-with-multiple-join-conditions by cc-by-sa and MIT license