【问题标题】:How do you left join using "date between" operator in linq?您如何在 linq 中使用“日期之间”运算符离开连接?
【发布时间】:2011-12-14 17:50:01
【问题描述】:

我有两张桌子。父表有一个日期列,子表有 2 个日期列(从/到)。我需要从父级到子级进行左连接,其中父级的日期列在子级之间。在 sql 中,这看起来像这样:

select p.cob, count(*) from parent p
left join child c on p.cob between c.effective and c.expiry
group by p.cob

如何在 linq 中编写这个 - 我有点卡在这里....

【问题讨论】:

  • 这个查询会很糟糕。
  • @BrianHoover - 为什么是VERY bad?这是时变关系的正常结构。
  • @Dems 因为它会给孩子和父母之间的笛卡尔连接。
  • @BrianHoover - 只有部分笛卡尔积。如果 p.cob 的范围延伸多年,但 c.effective 和 c.expiry 的平均跨度为数周或数月怎么办?这也是检查父母中每条记录有多少子关系的唯一方法。根据数据的不同,它可能是密集的,但它肯定不是错误的。

标签: .net sql linq


【解决方案1】:

这应该就是你要找的东西

var query = from p in context.Parent
            from c in context.Child.Where(x => p.cob >= x.effective)
                                   .Where(x => p.cob <= x.expiry)
                                   .DefaultIfEmpty()
            group p by p.cob into pg
            select new
            {
              cob = pg.Key,
              count = pg.Count()
            };

【讨论】:

  • 这可以满足我的需要,但是查询性能可能值得关注,因为探查器显示发送到 SQL 服务器的查询相当大且丑陋。我们将看到这是如何扩展的——这些表最终会变得相当大。
【解决方案2】:

旧的,但也许对其他人有帮助。它使我在特定数量的测试数据上的查询速度提高了 7 倍!

我有(28 秒)

from st in subtable
join t in table on st.IdTable equals t.Id
Where t.date >= myStartDate
&& t.date <= myEndDate
&& st == some_other_conditions
select st

我把它改成了这个(4秒)

from st in subtable
join t in table on new { parent = st.IdTable, from = 1, to = 1 } equals new { parent = t.Id, from = (t.date >= myStartDate ? 1 :  0), to = (t.date <= myEndDate ? 1 : 0 )
Where st == some_other_conditions
select st

它在创建连接结果后检查其他条件,以便所有其他条件都适用于更少量的数据。

希望对你有帮助

【讨论】:

    【解决方案3】:

    如果我正确阅读了您的问题,between 部分将像这样处理。

    where p.cob >= c.effective and p.cob <= c.expiry
    

    【讨论】:

      【解决方案4】:

      我需要从父级到子级进行左连接

      在 SQL 中表达需求的方式总是不止一种,我相信 linq 也是如此,例如

      SELECT p.cob, COUNT(*) 
        FROM parent p
       WHERE EXISTS (
                     SELECT * 
                       FROM child c 
                      WHERE p.cob BETWEEN c.effective AND c.expiry
                    )
       GROUP 
          BY p.cob
      UNION
      SELECT p.cob, 0 
        FROM parent p
       WHERE NOT EXISTS (
                         SELECT * 
                           FROM child c 
                          WHERE p.cob BETWEEN c.effective AND c.expiry
                        );
      

      一个好的优化器会发现重复的派生表,两个联合表是互斥的,等等。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多