sql - 将 UNION ALL 与 GROUP BY 结合
问题描述
我真的可以对这个查询使用一点帮助。
我有一张Products
桌子。
CREATE TABLE [dbo].[Products](
[Id] [int] NOT NULL,
[Title] [nvarchar](50) NOT NULL,
-- Additional column omitted
CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED
(
[Id] ASC
) ON [PRIMARY]
) ON [PRIMARY]
还有一张Transactions
桌子。
CREATE TABLE [dbo].[Transactions](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ProductId] [int] NOT NULL,
[TimeStamp] [datetime] NOT NULL,
[Quantity] [decimal](9, 3) NOT NULL,
[TotalAmount] [bigint] NOT NULL,
-- Additional columns omitted
CONSTRAINT [PK_Transactions] PRIMARY KEY CLUSTERED
(
[Id] ASC
) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[Transactions] WITH CHECK ADD CONSTRAINT [FK_Transactions_Products] FOREIGN KEY([ProductId])
REFERENCES [dbo].[Products] ([Id])
还有一张CCTransactions
桌子。
CREATE TABLE [dbo].[CCTransactions](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ProductId] [int] NOT NULL,
[TimeStamp] [datetime] NOT NULL,
[Quantity] [decimal](9, 3) NOT NULL,
[TotalAmount] [bigint] NOT NULL,
-- Additional columns omitted
CONSTRAINT [PK_CCTransactions] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
) ON [PRIMARY]
ALTER TABLE [dbo].[CCTransactions] WITH CHECK ADD CONSTRAINT [FK_CCTransactions_Products] FOREIGN KEY([ProductId])
REFERENCES [dbo].[Products] ([Id])
我需要一个属于给定日期范围内UNION ALL
的所有Transactions
和的查询,然后将它们分组为, , , 。CCTransactions
Product.Id
Product.Title
SUM(Quantity)
SUM(TotalAmount)
以下是我到目前为止所拥有的。它不会编译,但我包括在内,因为人们通常想看看你尝试了什么。它告诉我:
消息 8120,级别 16,状态 1,第 5
行列“Products.Id”在选择列表中无效,因为它不包含在聚合函数或 GROUP BY 子句中。
消息 209,级别 16,状态 1,第 14 行
不明确的列名称“Id”。
我了解这些错误,但不确定修复它们的最佳方法。在我添加联合之前,查询似乎正在工作。
DECLARE @dtStart DATE = '2016-08-01';
DECLARE @dtEnd DATE = '2016-08-31';
SELECT p.Id, p.Title, SUM(t.Quantity), SUM(t.TotalAmount) AS Amount
FROM Transactions t
INNER JOIN Products p ON t.ProductId = p.Id
WHERE t.[TimeStamp] >= @dtStart AND CAST(t.[TimeStamp] AS DATE) <= @dtEnd
UNION ALL
SELECT p.Id, p.Title, SUM(t.Quantity), SUM(t.TotalAmount) AS Amount
FROM CCTransactions t
INNER JOIN Products p ON t.ProductId = p.Id
WHERE t.[TimeStamp] >= @dtStart AND CAST(t.[TimeStamp] AS DATE) <= @dtEnd
GROUP BY p.Id, p.Title
ORDER BY Title
解决方案
你需要2个单独GROUP BY
的s:
SELECT p.Id, p.Title, SUM(t.Quantity), SUM(t.TotalAmount) AS Amount
FROM Transactions t
INNER JOIN Products p ON t.ProductId = p.Id
WHERE t.[TimeStamp] >= @dtStart AND CAST(t.[TimeStamp] AS DATE) <= @dtEnd
GROUP BY p.Id, p.Title
UNION ALL
SELECT p.Id, p.Title, SUM(t.Quantity), SUM(t.TotalAmount) AS Amount
FROM CCTransactions t
INNER JOIN Products p ON t.ProductId = p.Id
WHERE t.[TimeStamp] >= @dtStart AND CAST(t.[TimeStamp] AS DATE) <= @dtEnd
GROUP BY p.Id, p.Title
或子查询:
SELECT X.id, X.Title, SUM(X.Quantity), SUM(X.TotalAmount)
FROM (
SELECT p.Id, p.Title, t.Quantity, t.TotalAmount
FROM Transactions t
INNER JOIN Products p ON t.ProductId = p.Id
WHERE t.[TimeStamp] >= @dtStart AND CAST(t.[TimeStamp] AS DATE) <= @dtEnd
UNION ALL
SELECT p.Id, p.Title, t.Quantity, t.TotalAmount
FROM CCTransactions t
INNER JOIN Products p ON t.ProductId = p.Id
WHERE t.[TimeStamp] >= @dtStart AND CAST(t.[TimeStamp] AS DATE) <= @dtEnd
) X
GROUP BY X.Id, X.Title
或者您可以重写整个查询:
;WITH
AllTransaction AS
(
SELECT ProductID, Timestamp, Quantity, TotalAmount
FROM Transaction
UNION ALL
SELECT ProductID, Timestamp, Quantity, TotalAmount
FROM CCTransaction
)
SELECT p.Id, p.Ttitle, SUM(t.Quantity), SUM(t.TotalAmount)
FROM AllTransaction t
INNER JOIN Products p ON t.ProductId = p.Id
WHERE @dtStart <= t.[Timestamp] AND t.[TimeStamp] < DATEADD(DAY, 1, @dtEnd)
GROUP BY p.Id, p.Title
注意 CAST(t.[TimeStamp] AS DATE) <= @dtEnd
:这种情况不是SARGable,这意味着索引和统计数据没有帮助。CAST(t.[TimeStamp] AS DATE)
在您将函数应用于每一行之前,结果是未知的。这会导致表扫描(即读取整个表),而您可能只需要几行。如果Transactions
和CCTransactions
是巨大的,你会受苦。
推荐阅读
- sql - 如何检查表中是否存在值 - postgres PLPGSQL
- authentication - JHipster:如何限制用户使用 REST 访问自己的数据
- php - 不正确的 player_id 格式(不是有效的 UUID)
- javascript - Javascript:从 .cvs 文件中的两列创建数组
- python - 使用 Python 套接字 UDP IPV6 接收特定源地址和端口的数据
- unity3d - 相机聚焦对象中心
- javascript - 如何为我的 Discord 机器人提供的统计信息创建嵌入(Covid 统计)
- vba - 仅从电子邮件中提取 excel 文档
- c - 通过将第二个字符串的字符一个接一个地复制到第一个字符串的末尾来合并两个字符串
- python - 有返回问题的总和的所有路径