Конвертировать SQL-запрос с вложенной суммой в linq2sql - PullRequest
0 голосов
/ 27 января 2012

Я пытаюсь преобразовать этот SQL-запрос в запрос Linq2SQL, однако я просто перетаскиваю хранимую процедуру в dbml и надеюсь, что кто-то сможет сделать лучше. Если для вложенного запроса нет записей, он возвращает ноль.

SQL:

SELECT
    Table1.Field1 -
    ISNULL(
            (
            SELECT  
                SUM(Table2.Field1) 
            FROM Table2 
                INNER JOIN Table3 ON Table2.ID = Table3.Table2ID 
            WHERE Table3.Table1ID = Table1.ID
            )
            ,0)
FROM
    Table1
WHERE
    (Table1.ID = @ID)

Linq2SQL

     return (from q in db.Table1s
                    where q.ID == id
                    select q.Field1.GetValueOrDefault() - 
                            (from o in db.Table2s 
                             join r in db.Table3s on o.ID equals r.Table2ID.GetValueOrDefault(0)
                             where r.Table1ID == q.ID
                             select Convert.ToInt32(o.Field1.GetValueOrDefault(0))).Sum()
                    ).SingleOrDefault()

Может ли кто-нибудь сделать лучшую работу.

Ответы [ 2 ]

2 голосов
/ 27 января 2012

Краткая версия с использованием синтаксиса метода и лямбда-выражений:

from t1 in Table1s
select t1.Field1 -  Table3s.Where(x=>x.Table1ID == t1.ID).Sum(y=>y.Table2.Field1)

Более читаемая версия с использованием синтаксиса запроса с оператором let:

from t1 in Table1s
let tmp = 
(
    from t3 in Table3s
    where t3.Table1ID == t1.ID
    select t3.Table2.Field1
).Sum()
select t1.Field1 -  tmp

Я настоятельно рекомендую использовать такой инструмент, как LinqPad , для разработки ваших запросов, поскольку он покажет вам сгенерированный SQL. Это позволяет настроить более дорогие запросы для получения лучших результатов.

Это также полезно для быстрого создания прототипов и тестирования коротких блоков кода.

1 голос
/ 27 января 2012

Это может помочь: Я бы сформулировал sql по-другому. Как это:

SELECT
    Table1.Field1 - ISNULL(tblTemp.SumOfField1,0)
FROM
    Table1
    LEFT JOIN
        (
            SELECT  
                SUM(Table2.Field1) AS SumOfField1,
                Table3.Table1ID
            FROM Table2 
                INNER JOIN Table3 ON Table2.ID = Table3.Table2ID 
            GROUP BY 
                Table3.Table1ID
        ) AS tblTemp
        ON tblTemp.Table1ID = Table1.ID
WHERE
    Table1.ID = @ID

И тогда ваш код linq может быть таким (такой же результат, просто другой взгляд на это):

var leftJoin=(
                    from Table2 in db.Table2
                    join Table3 in db.Table3
                        on Table2.ID equals Table3.Table2ID 
                    group Table3 by Table3.Table1ID into g
                    select new
                    {
                        Table1ID=g.Key,
                        SumOf= g.Sum (x =>x.Field1 )
                    }
                );
var output=(
        from Table1 in db.Table1
        from g in leftJoin
            .Where (a =>a.Table1ID==Table1.ID).DefaultIfEmpty()
        select new
        {
            Table1.ID,
            SumOf=(g.SumOf??0)-Table1.Field1
        }
    );
...