【问题标题】:SQL to LINQ - multiple tables left outer join with where clause referring right tableSQL to LINQ - 多个表左外连接,where子句引用右表
【发布时间】:2018-03-07 17:58:01
【问题描述】:

我有以下查询并想转换为 LINQ。

我尝试过 LINQPad 和 Linqer,但在 Visual Studio 中出现错误。

SELECT DISTINCT
                g.TXT_Property,
                up.TXT_Page
            FROM MD g

            LEFT JOIN MD ux ON ux.TXT_Page = @sPage 
                AND ux.TXT_Property = g.TXT_Property 
                AND ux.TXT_Product = @sProdAll 
                AND ux.GID_Section IS NULL

            LEFT JOIN MD up ON up.TXT_Page = @sPage 
                AND up.TXT_Property = g.TXT_Property 
                AND (ISNULL(up.TXT_Product, '') = @sProd or up.TXT_Product = @sProdAlt) 
                AND up.GID_Section IS NULL
            WHERE 

                (g.GID_Section IS NULL) 
                AND g.TXT_Page = @sPage 
                and (ISNULL(g.TXT_Product, '') = @sProd or g.TXT_Product = @sProdAlt or g.TXT_Product = @sProdAll)
            ORDER BY TXT_Property, TXT_Product, TXT_Language

这是我尝试过的:

                var query2 = from g in list
                             join ux in list
                                  on g.Property equals ux.Property into g_ux
                             where ux.Page == sPage
                             && ux.Product == sProdAll
                             && ux.Section == null 

这是另一个尝试。

我提到过 SQL to LINQ - multiple tables left outer join with where clause referring right table

// 另一个查询

var query = (from g in
                                 ((from d in list
                                   where ((d.Section == null || d.Section == uSection) && (d.Product == sProd || (sProd == "" && d.Product == null) || (d.Product == sProdAlt) || (d.Product == sProdAll)))
                                   select (new { d.Property })).ToList())

                             join gx in
                                 ((from d in list
                                   where (d.Section == null) && (d.Product == sProdAll)
                                   select (new { d.Property, d.Page, d.Product, d.Language, d.Value, d.Section })).ToList())
                                     on g.Property equals gx.Property into res1
                             from a1 in res1.DefaultIfEmpty()

                             join gp in
                                 ((from d in list
                                   where (d.Section == null) && (d.Product == sProd || (sProd == "" && d.Product == null) || (d.Product == sProdAlt))
                                   select (new { d.Property, d.Page, d.Product, d.Language, d.Value, d.Section })).ToList())
                                   on g.Property equals gp.Property into res2
                             from a2 in res2.DefaultIfEmpty()

                             join ux in
                                 ((from d in list
                                   where (d.Section == uSection) && (d.Product == sProdAll)
                                   select (new { d.Property, d.Page, d.Product, d.Language, d.Value, d.Section })).ToList())
                                   on g.Property equals ux.Property into res3
                             from a3 in res3.DefaultIfEmpty()

                             join up in
                                 ((from d in list
                                   where (d.Section == uSection) && (d.Product == sProd || (sProd == "" && d.Product == null) || (d.Product == sProdAlt))
                                   select (new { d.Property, d.Page, d.Product, d.Language, d.Value, d.Section })).ToList())
                                     on g.Property equals up.Property into res4
                             from a4 in res4.DefaultIfEmpty()

                             orderby (new
                             {
                                 TXT_Property = g.Property,
                                 TXT_Product = Coalesce((Coalesce(a4.Page, "") == "" ? Coalesce(a4.Product, a3.Product) : Coalesce(a4.Product, "SA")), a3.Product, (Coalesce(a2.Page, "") == "" ? Coalesce(a2.Product, a1.Product) : Coalesce(a2.Product, "SA")), a1.Product),
                                 TXT_Language = Coalesce(a4.Language, a3.Language, a2.Language, a1.Language),
                             })
                             select (new
                             {
                                 TXT_Property = g.Property,
                                 TXT_Product = Coalesce((Coalesce(a4.Page, "") == "" ? Coalesce(a4.Product, a3.Product) : Coalesce(a4.Product, "SA")), a3.Product, (Coalesce(a2.Page, "") == "" ? Coalesce(a2.Product, a1.Product) : Coalesce(a2.Product, "SA")), a1.Product),
                                 TXT_Language = Coalesce(a4.Language, a3.Language, a2.Language, a1.Language),
                                 TXT_Value = Coalesce(a4.Value, a3.Value, a2.Value, a1.Value)
                             }));

【问题讨论】:

  • 您可能想要发布一些您尝试过的代码,否则您可能会投下反对票,并且可能无法获得太多帮助。

标签: c# linq


【解决方案1】:

您的 SQL 查询对我来说似乎很可疑(因为 ux 是 LEFT JOIN 并且(可能)没有在查询的其余部分中引用,它没有添加任何内容),我不得不假设 ORDER BY 在 @ 987654323@ 列,因为它没有被指定(我很惊讶没有被 SQL 拒绝为模棱两可),但这是我的翻译尝试:

var ans = from g in MD
          join ux in MD on new { TXT_Page = sPage, g.TXT_Property, TXT_Product = sProdAll, GID_Section = (string)null } equals new { ux.TXT_Page, ux.TXT_Property, ux.TXT_Product, ux.GID_Section } into uxj
          from ux in uxj.DefaultIfEmpty()
          join up in MD on new { TXT_Page = sPage, g.TXT_Property, GID_Section = (string)null } equals new { up.TXT_Page, up.TXT_Property, up.GID_Section } into upj
          from up in upj.DefaultIfEmpty()
          where up == null || (up.TXT_Product ?? "") == sProd || up.TXT_Product == sProdAlt
          where g.GID_Section == null && g.TXT_Page == sPage &&
                ((g.TXT_Product ?? "") == sProd || g.TXT_Product == sProdAlt || g.TXT_Product == sProdAll)
          orderby g.TXT_Property, g.TXT_Product, g.TXT_Language
          select new { g.TXT_Property, up.TXT_Page };

注意:我输入了up == null,因为否则where 可能会拒绝SQL 中LEFT JOIN 不会拒绝的地方。

我假设GID_Section 的类型是string,但您可以将nulls 转换为正确的类型。

这是我的 SQL 转换方法,虽然你的 SQL 有点棘手,因为它结合了 LEFT JOIN 和非等值连接。

用于将 SQL 转换为 LINQ 查询理解:

  1. FROM 子选择转换为单独声明的变量。
  2. 按 LINQ 子句顺序翻译每个子句,将单子和聚合运算符(DISTINCTTOPMINMAX 等)翻译成应用于整个 LINQ 查询的函数。
  3. 使用表别名作为范围变量。使用列别名作为匿名类型字段名称。
  4. 对多个列使用匿名类型 (new { ... })。
  5. JOIN 不是所有与 AND 相等性测试的条件必须使用连接外部的 where 子句或叉积 (from ... from ...) 然后 where
  6. JOIN 两个表之间的多个 ANDed 相等测试条件应转换为匿名对象
  7. LEFT JOIN 是通过使用 into joinvariable 模拟的,然后从 from joinvariable 执行另一个操作,然后是 .DefaultIfEmpty()
  8. COALESCE 替换为条件运算符 (?:) 和 null 测试。
  9. IN 转换为.Contains()NOT IN 转换为!...Contains(),对常量列表使用文字数组或数组变量。
  10. x BETWEEN low AND high 转换为 low <= x && x <=
  11. CASE 转换为三元条件运算符?:
  12. SELECT * 必须替换为 select range_variable 或对于连接,一个包含所有范围变量的匿名对象。
  13. SELECT 字段必须替换为 select new { ... } 创建一个包含所有所需字段或表达式的匿名对象。
  14. 必须使用扩展方法处理正确的FULL OUTER JOIN

【讨论】:

    猜你喜欢
    • 2013-06-13
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多