5

我遇到了以下伪查询的问题:

var daily = from p in db.table1
            group p by new
            {
                key1,
                key2
            } into g
            join d in db.table2
            on new { p.key1, p.key2 } equals { d.key1, d.key2 }
            select new
            {
                col1 = g.Key.key1
                col2 = g.Sum(a => a.column2)
                col3 = d.column3
            };

它运行,但生成的 LINQ 发送到 SQL Server 的 SQL 语句是荒谬的。实际实现遵循与上面类似的设置,有 7 个左右的列,每个列都有一个 .Sum() 计算。生成的 SQL 大约有 10-11 个嵌套的 SELECT 语句,没有 INNER JOIN,当然,运行需要很长时间。

我测试了查询的另一个实现:

var daily = from p in
                (from p in db.table1
                 group p by new
                 {
                     key1,
                     key2
                 } into g
                 select new
                 {
                     col1 = g.Key.key1,
                     col2 = g.Sum(a => a.column2)
                 })
            join d in db.table2
            on new { p.key1, p.key2 } equals new { d.key1, d.key2 }
            select new
            {
                col1 = p.col1,
                col2 = p.col2,
                col3 = d.column3
            };

这个版本使用单个 SUB-SELECT 和一个 INNER JOIN 语句生成更合理的 SQL(它也几乎立即运行)。我讨厌的一点是,恕我直言,第一个 LINQ 查询更加直接和简洁,而第二个查询似乎相当多余,因为我最终不得不从 table1 定义我想要的所有列两次。

为什么这两个相似的查询在服务器上执行如此不同,为什么查询 2 的效率要高得多,尽管它的代码表达力要差得多?

有没有办法可以将第一个查询重写为与第二个查询一样高效?

4

1 回答 1

6

LINQ 2 SQL 存在以下模式的问题:

from t in table
group t by key into g
from t in g //"ungroup" the grouping - this is causing a problem
select ...

我认为您的加入触发了这一点,因为它“取消了”分组。请注意,LINQ 连接是一种GroupJoin在 SQL 中无法表示的连接。想一想:你会如何翻译我的示例查询?您必须加入导致疯狂冗余table的分组版本。table

我已经多次看到这个问题。您找到了正确的解决方法:强制投影以防止出现这种模式。

有一个稍微不那么尴尬的版本:

var daily = from p in db.table1
            group p by new
            {
                key1,
                key2
            } into g
            select new
            {
                col1 = g.Key.key1,
                col2 = g.Sum(a => a.column2)
            } into p
            join d in db.table2 on new { p.key1, p.key2 } equals new { d.key1, d.key2 }
            select new
            {
                col1 = p.col1,
                col2 = p.col2,
                col3 = d.column3
            };

嵌套被鲜为人知的select x into y语法删除。

于 2012-12-28T00:16:58.423 回答