MSI*_*SIS 5 sql-server sql-server-2012
希望有人能澄清如何从 SQL Server 2012 中执行此查询,或者它可能在问什么;似乎我被要求做一个将聚合与非聚合相结合的查询,这导致了一个看似不可能的查询,因为一个人只能按出现在Select子句中的字段进行分组,这会使查询变得混乱。
我被要求对表进行查询Invoices:
Invoices (InvoiceID, VendorID,InvoiceDate, InvoiceTotal,...)
Run Code Online (Sandbox Code Playgroud)
我被要求执行一个生成 6 列的查询:3 列已经“按原样”出现在表中: VendorID, InvoiceDate, InvoiceTotal
其他 3 列是聚合:
4) Sum(InvoiceTotal) AS VendorTotal: 每个发票的总和VendorID
5) Count(InvoiceID) AS VendorCount: 每个发票的数量VendorId
6) Avg(InvoiceTotal) AS VendorAvg: 平均每张发票VendorId
现在,问题是不能在同一个查询中组合(除了我不能在这里使用的例外)聚合和非聚合,除非按非聚合分组。所以我可以这样做:
Select
VendorId, InvoiceDate, InvoiceTotal,
Sum(InvoiceTotal) AS VendorTotal,
Count(InvoiceId) AS VendorCount,
Avg(InvoiceTotal) AS VendorAvg
GROUP BY
VendorID
Run Code Online (Sandbox Code Playgroud)
现在,如果我只是group by VendorID. 但是为了获得有效的查询,如果我选择其中一个InvoiceDate或InvoiceTotal——两个非聚合——我必须按它们中的每一个分组以获得有效的查询。
但是按这最后两个分组基本上会撤消其他聚合:如果我按发票日期分组,我将丢失按供应商的聚合,因为每个供应商都有不同的发票日期。
我尝试过进行自联接,在 中使用Invoices AS I1 join Invoices AS I2
和进行聚合,在 上I1进行非聚合I2,但这似乎不起作用。
我在这里遗漏了一些明显的东西吗?有任何想法吗?
编辑:发现答案正在使用OVER (PARTITION BY VendorId),如下所示:
Select
VendorId, InvoiceDate, InvoiceTotal,
Sum(InvoiceTotal) OVER (PARTITION BY VendorId) AS VendorTotal,
Count(InvoiceId) OVER (PARTITION BY VendorId) AS VendorCount,
Avg(InvoiceTotal) OVER (PARTITION BY VendorId) AS VendorAvg
GROUP BY
VendorID
Run Code Online (Sandbox Code Playgroud)
解决方案是你已经发现的,在像 SQL Server 2005+ 这样已经实现窗口函数的 DBMS 中,我们可以使用它们来获取over每个聚合,partition同时保留原始表,因此不会像这样折叠表group by。我不是在这里写查询,请编辑您的答案。
在没有OVER ()可用子句语法的旧版本(或其他 DBMS)中,我们可以GROUP BY在派生表(或 CTE)中使用,然后“self”连接回原始表,如下所示:
SELECT
i.VendorID, i.InvoiceDate, i.InvoiceTotal,
grp.VendorTotal,
grp.VendorCount,
grp.VendorAvg
FROM
dbo.Invoices AS i -- our original table
JOIN
( SELECT
VendorID,
Sum(InvoiceTotal) AS VendorTotal,
Count(InvoiceId) AS VendorCount,
Avg(InvoiceTotal) AS VendorAvg
FROM
dbo.Invoices
GROUP BY
VendorID
) AS grp -- the aggregated table
ON
grp.VendorID = i.VendorID ;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2861 次 |
| 最近记录: |