我正在SQL Server 2008中编写一个查询(我相信Express吗?)。我目前收到此错误:
Msg 8120,Level 16,State 1,Line 16
列'AIM.dbo.AggTicket.TotDirectHrs'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。
我正在尝试对我们的生产WIP(在制品)进行历史分析。 我创建了一个独立的日历表(实际上位于同一服务器上名为BAS的单独数据库中,不会干扰运行AIM数据库的ERP)。我已经被一些用于创建运行总查询/视图/表的示例所淹没了几天,所以现在我只打算在Crystal Reports 2016中处理该部分。我的想法是我想要返回我的日历表每天每个订单的记录(将来缩小到仅与AIM数据库中的记录匹配的天数)。我认为我需要的价值观是:
我使用的表格如下:
BAS数据库:
AIM数据库:
以下是我在查询中使用的代码:
;WITH OrderTots AS
(
SELECT
AggTicket.OrderNo,
SUM(AggTicket.TotDirectHrs) AS TotActHrs
FROM
AIM.dbo.AggTicket
GROUP BY
AggTicket.OrderNo
)
SELECT
d.Date,
t.OrderNo,
o.EstHrs,
OrderTots.TotActHrs,
SUM(t.TotDirectHrs) OVER (PARTITION BY t.TicketDate) AS DaysDirectHrs,
COUNT(a.EmplCode) AS NumEmployees,
SUM(a.TotHrs) AS DaysAttendHrs
FROM
BAS.dbo.DateDimension d
INNER JOIN
AIM.dbo.AggAttend a ON d.Date = a.TicketDate
LEFT OUTER JOIN
AIM.dbo.AggTicket t ON d.Date = t.TicketDate
LEFT OUTER JOIN
AIM.dbo.ModOrders o ON t.OrderNo = o.OrderNo
LEFT OUTER JOIN
OrderTots ON t.OrderNo = OrderTots.OrderNo
GROUP BY
d.Date, t.TicketDate, t.OrderNo, o.EstHrs,
OrderTots.TotActHrs
ORDER BY
d.Date
当我在SQL Server Management Studio 2017中运行该查询时,出现上述错误。
这些是我对社区的问题:
提前感谢所有人!
答案 0 :(得分:0)
我正在SQL Server 2008中编写一个查询(我相信Express吗?)。
SELECT @@VERSION
会让你知道你的版本。
专栏' AIM.dbo.AggTicket.TotDirectHrs'在选择列表中无效 因为它不包含在聚合函数或 GROUP BY子句。
问题在于您的SUM OVER()
声明:
SUM(t.TotDirectHrs) OVER (PARTITION BY t.TicketDate) AS DaysDirectHrs
此处,由于您使用的是OVER
子句,因此必须将其包含在GROUP BY
中。 OVER
子句用于确定窗口函数的行集的分区和顺序。因此,当您使用SUM
聚合时,您正在窗口函数中执行此操作。窗口函数属于一种称为“设置函数”的函数,它表示适用于一组行的函数。单词' window'用于指代函数处理的行集。
因此,将t.TotDirectHrs
添加到GROUP BY
GROUP BY
d.Date, t.TicketDate, t.OrderNo, o.EstHrs,
OrderTots.TotActHrs, t.TotDirectHrs
如果这会将您的结果缩小为您不想要的分组,那么您可以将其包装在另一个CTE
中或使用相关的子查询。 潜在如下所示:
(SELECT SUM(t2.TotDirectHrs) OVER (PARTITION BY t2.TicketDate) AS DaysDirectHrs FROM AIM.dbo.AggTicket t2 WHERE t2.TicketDate = t.TicketDate) as DaysDirectHrs,
示例强>
if object_id('tempdb..#test') is not null
drop table #test
create table #test(id int identity(1,1), letter char(1))
insert into #test
values
('a'),
('b'),
('b'),
('c'),
('c'),
('c')
鉴于上面的数据集,假设我们想要获得所有行的计数。这很简单吧?
select
TheCount = count(*)
from
#test
+----------+
| TheCount |
+----------+
| 6 |
+----------+
此处不需要GROUP BY
,因为它隐含在所有列上进行分组,因为SELECT
列表中未指定任何列。请记住,GROUP BY
根据一个或多个列表达式列表中的值对SELECT语句结果进行分组。如果聚合函数包含在SELECT列表中,GROUP BY将计算每个组的汇总值。这些被称为矢量聚合。[MSDN] 。
现在,假设我们想要计算表格中的每个字母。我们至少可以通过两种方式做到这一点。将COUNT(*)
与选择列表中的letter
列一起使用 - 或将COUNT(letter)
与letter
列一起使用在选择列表中。但是,为了让我们将计数归入字母,我们需要返回字母列。因此,我们必须在letter
中包含GROUP BY
,告诉SQL Server将摘要表应用到什么位置。
select
letter
,TheCount = count(*)
from
#test
group by
letter
+--------+----------+
| letter | TheCount |
+--------+----------+
| a | 1 |
| b | 2 |
| c | 3 |
+--------+----------+
现在,如果我们想要返回相同的计数,但我们想要返回所有行呢?这就是窗口函数的用武之地。在这种情况下,窗口函数与GROUP BY
的工作方式类似,告诉SQL Server应用聚合的行集。然后,为此窗口/分区中的每一行返回它的值。因此,它返回一个应用于每一行的列,使其与从选择列表返回的任何列或计算列一样。
select
letter
,TheCountOfTheLetter = count(*) over (partition by letter)
from
#test
+--------+---------------------+
| letter | TheCountOfTheLetter |
+--------+---------------------+
| a | 1 |
| b | 2 |
| b | 2 |
| c | 3 |
| c | 3 |
| c | 3 |
+--------+---------------------+
现在我们来看一下你想要在窗口函数中使用聚合和聚合的情况。请记住,窗口函数的返回与任何其他列一样,因此必须应用于GROUP BY
。 Pseudo看起来像这样,但GROUP BY
子句中不允许使用窗口函数。
select
letter
,TheCount = count(*)
,TheCountOfTheLetter = count(*) over (partition by letter)
from
#test
group by
letter
,count(*) over (partition by letter)
--returns an error
因此,我们必须使用相关的子查询或cte或其他方法。
select
t.letter
,TheCount = count(*)
,TheCountOfTheLetter = (select distinct count(*) over (partition by letter) from #test t2 where t2.letter = t.letter)
from
#test t
group by
t.letter
+--------+----------+---------------------+
| letter | TheCount | TheCountOfTheLetter |
+--------+----------+---------------------+
| a | 1 | 1 |
| b | 2 | 2 |
| c | 3 | 3 |
+--------+----------+---------------------+