Search code examples
c#sqlentity-framework-6linqer

Linqer cannot convert: SQL syntax error: Each GROUP BY expression must contain at least one column reference


I have this running query:

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 is not able to convert this to proper LINQ:

SQL syntax error: Each GROUP BY expression must contain at least one column reference.

This query is working in SQL Server. Any pointers?

Note:

  • Removing the DISTINCT has no effect
  • Removing the ORDER BY has no effect
  • Removing the ; has no effect

Solution

  • Seems that all I had to do was to remove the CASE with PAY_MODE_ID. I modified the query apart from that change in order to make it production ready:

    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
    

    This resulted in LINQ (slightly modified):

        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)
        }