Linqer无法转换:SQL语法错误:每个GROUP BY表达式必须至少包含一个列引用

问题描述 投票:0回答:2

我有这个运行查询:

SELECT DISTINCT
       b.NAME AS [Service Name],
       CASE
           WHEN [a].[PAY_MODE_ID] IN ( 1, 2 ) THEN
               'OFFLINE'
           ELSE
               'ONLINE'
       END AS [Transaction Type],
       p.NAME AS [Payment Method],
       SUM(a.REQUESTED_QTY) AS [Transaction],
       SUM(a.ITEM_TOTAL) AS Income
FROM dbo.BILL_INFO_DETAIL AS a
    INNER JOIN dbo.SERVICE_INFO AS b
        ON a.SERVICE_CODE = b.SERVICE_CODE
    INNER JOIN dbo.PAY_MODE AS p
        ON a.PAY_MODE_ID = p.PAY_MODE_ID
WHERE (a.INPUT_STATUS = '1')
      AND (b.SERVICE_CODE IN ( 1610, 1611, 1612 ))
      AND (CONVERT(VARCHAR(2), a.STAMP_DATE, 101) IN ( '10', '11', '12' ))
      AND (CONVERT(VARCHAR(4), a.STAMP_DATE, 102) IN ( '2017' ))
      AND (b.FEE > 1)
GROUP BY b.NAME,
         CASE
             WHEN [a].[PAY_MODE_ID] IN ( 1, 2 ) THEN
                 'OFFLINE'
             ELSE
                 'ONLINE'
         END,
         p.NAME
ORDER BY [Transaction Type];

Linqer无法将其转换为正确的LINQ:

SQL语法错误:每个GROUP BY表达式必须至少包含一个列引用。

此查询在SQL Server中有效。有什么指针吗?

注意:

  • 删除DISTINCT没有任何影响
  • 删除ORDER BY没有任何影响
  • 删除;没有任何影响
c# sql entity-framework-6 linqer
2个回答
3
投票

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

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

所以对于你的查询,

FULL OUTER JOIN

0
投票

似乎我所要做的就是用PAY_MODE_ID删除CASE。我修改了除该更改之外的查询,以使其生产就绪:

var ans = (from a in dbo.BILL_INFO_DETAIL
           join b in dbo.SERVICE_INFO on a.SERVICE_CODE equals b.SERVICE_CODE
           join p in dbo.PAY_MODE on a.PAY_MODE_ID equals p.PAY_MODE_ID
           where (a.INPUT_STATUS == "1") &&
                 (new[] { 1610, 1611, 1612 }.Contains(b.SERVICE_CODE)) &&
                 (new[] { 10, 11, 12 }.Contains(a.STAMP_DATE.Month)) &&
                 (new[] { 2017 }.Contains(a.STAMP_DATE.Year)) &&
                 (b.FEE > 1)
           let TransactionType = new[] { 1, 2 }.Contains(a.PAY_MODE_ID) ? "OFFLINE" : "ONLINE"
           group new { a, b, p } by new { bName = b.NAME, TransactionType, pName = p.NAME } into abpg
           orderby abpg.Key.TransactionType
           select new {
               Service_Name = abpg.Key.bName,
               TransactionType = abpg.Key.TransactionType,
               Payment_Method = abpg.Key.pName,
               Transaction = abpg.Sum(abp => abp.a.REQUESTED_QTY),
               Income = abpg.Sum(abp => abp.a.ITEM_TOTAL)
           }).Distinct();

这导致了LINQ(略有修改):

SELECT si.SERVICE_CODE,     
       si.NAME AS [ServiceName],
       bid.PAY_MODE_ID AS [PaymentId],
       p.NAME AS [PaymentName],
       SUM(bid.REQUESTED_QTY) AS [Transaction],
       SUM(bid.ITEM_TOTAL) AS [Income]
FROM BILL_INFO_DETAIL AS bid
    INNER JOIN dbo.SERVICE_INFO AS si
        ON bid.SERVICE_CODE = si.SERVICE_CODE
    INNER JOIN dbo.PAY_MODE AS p
        ON bid.PAY_MODE_ID = p.PAY_MODE_ID
WHERE (bid.INPUT_STATUS = '1')
      AND (si.SERVICE_CODE IN ( 1610, 1611, 1612 ))
      AND (CONVERT(VARCHAR(2), bid.STAMP_DATE, 101) IN ( '10', '11', '12' ))
      AND (CONVERT(VARCHAR(4), bid.STAMP_DATE, 102) IN ( '2017' ))
      AND (si.FEE > 1)
GROUP BY si.SERVICE_CODE,
         si.NAME,   
         bid.PAY_MODE_ID,
         p.NAME
© www.soinside.com 2019 - 2024. All rights reserved.