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

时间:2018-03-06 18:53:05

标签: c# sql entity-framework-6 linqer

我有这个正在运行的查询:

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无效
  • 删除;无效

2 个答案:

答案 0 :(得分:3)

将SQL转换为LINQ查询理解:

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

    SELECT

答案 1 :(得分:0)

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

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

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

    from bid in db.BILL_INFO_DETAIL
    where
      bid.INPUT_STATUS == true &&
      (new int[] {1610, 1611, 1612 }).Contains(bid.SERVICE_INFO.SERVICE_CODE) &&
      (new int[] {10, 11, 12 }).Contains(bid.STAMP_DATE.Value.Month) &&
      bid.STAMP_DATE.Value.Year == 2017 &&
      bid.SERVICE_INFO.FEE > 1
    group new {bid.SERVICE_INFO, bid, bid.PAY_MODE} by new {
      bid.SERVICE_INFO.SERVICE_CODE,
      bid.SERVICE_INFO.NAME,
      bid.PAY_MODE_ID,
      Column1 = bid.PAY_MODE.NAME
    } into g
    select new {
      g.Key.SERVICE_CODE,
      ServiceName = g.Key.NAME,
      PaymentId = g.Key.PAY_MODE_ID,
      PaymentName = g.Key.NAME,
      Transaction = (int?)g.Sum(p => p.bid.REQUESTED_QTY),
      Income = (decimal?)g.Sum(p => p.bid.ITEM_TOTAL)
    }