Linqer cannot convert: SQL syntax error: Each GROUP BY expression must contain at least one column reference
Linqer cannot convert: SQL syntax error: Each GROUP BY expression must contain at least one column reference
我有这个 运行 查询:
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 syntax error: Each GROUP BY expression must contain at least one column reference.
此查询正在 SQL 服务器中运行。有什么指点吗?
注:
- 删除
DISTINCT
没有效果
- 删除
ORDER BY
没有效果
- 删除
;
没有效果
将 SQL 转换为 LINQ 查询理解:
- 将
FROM
subselects 翻译为单独声明的变量。
- 翻译 LINQ 子句顺序中的每个子句,将单子和聚合运算符(
DISTINCT
、TOP
、MIN
、MAX
等)翻译成应用于整体的函数LINQ 查询。
- 使用table别名作为范围变量。使用列别名作为匿名类型字段名称。
- 对多列使用匿名类型 (
new {
... }
)。
JOIN
并非所有与 AND
相等性测试的条件必须使用连接外部的 where
子句或叉积(from
.. . from
...) 然后 where
JOIN
条件是两个 table 之间的多个 AND
ed 相等性测试应该被翻译成匿名对象
LEFT JOIN
是通过使用 into
joinvariable 并从 from
中执行另一个 joinvariable 来模拟的] 然后是 .DefaultIfEmpty()
.
- 将
COALESCE
替换为条件运算符 (?:
) 和 null
测试。
- 将
IN
翻译成 .Contains()
并将 NOT IN
翻译成 !
...Contains()
,使用常量列表的文字数组或数组变量。
- 将x
BETWEEN
lowAND
high翻译成低 <=
x &&
x <=
高.
- 将
CASE
翻译成三元条件运算符?:
。
SELECT *
必须替换为 select range_variable 或对于连接,包含所有范围变量的匿名对象。
SELECT
字段必须替换为 select new {
... }
创建一个包含所有所需字段或表达式的匿名对象。
- 正确的
FULL OUTER JOIN
必须用扩展方法处理。
所以对于您的查询,
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();
似乎我所要做的就是用 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)
}
我有这个 运行 查询:
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 syntax error: Each GROUP BY expression must contain at least one column reference.
此查询正在 SQL 服务器中运行。有什么指点吗?
注:
- 删除
DISTINCT
没有效果 - 删除
ORDER BY
没有效果 - 删除
;
没有效果
将 SQL 转换为 LINQ 查询理解:
- 将
FROM
subselects 翻译为单独声明的变量。 - 翻译 LINQ 子句顺序中的每个子句,将单子和聚合运算符(
DISTINCT
、TOP
、MIN
、MAX
等)翻译成应用于整体的函数LINQ 查询。 - 使用table别名作为范围变量。使用列别名作为匿名类型字段名称。
- 对多列使用匿名类型 (
new {
...}
)。 JOIN
并非所有与AND
相等性测试的条件必须使用连接外部的where
子句或叉积(from
.. .from
...) 然后where
JOIN
条件是两个 table 之间的多个AND
ed 相等性测试应该被翻译成匿名对象LEFT JOIN
是通过使用into
joinvariable 并从from
中执行另一个 joinvariable 来模拟的] 然后是.DefaultIfEmpty()
.- 将
COALESCE
替换为条件运算符 (?:
) 和null
测试。 - 将
IN
翻译成.Contains()
并将NOT IN
翻译成!
...Contains()
,使用常量列表的文字数组或数组变量。 - 将x
BETWEEN
lowAND
high翻译成低<=
x&&
x<=
高. - 将
CASE
翻译成三元条件运算符?:
。 SELECT *
必须替换为 select range_variable 或对于连接,包含所有范围变量的匿名对象。SELECT
字段必须替换为select new {
...}
创建一个包含所有所需字段或表达式的匿名对象。- 正确的
FULL OUTER JOIN
必须用扩展方法处理。
所以对于您的查询,
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();
似乎我所要做的就是用 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)
}