如何获得两个查询结果集之间的差异
Posted
技术标签:
【中文标题】如何获得两个查询结果集之间的差异【英文标题】:How to get a difference between two query result sets 【发布时间】:2021-11-24 19:49:01 【问题描述】:我有两个问题。第一个查询的输出是所有品牌的总销售量,第二个查询的输出是“新”品牌的总销售量。 我只需要创建一个查询(通过合并以下两个查询:Query1 和 Query2),我们可以看到每个地区“新”品牌的总销售额、每个地区所有品牌的总销售额和一个名为差异的新列(总销售额的所有品牌 - 新品牌的总销量)并排。
预期输出:
InvoiceDate | Brand | Region | Quantity for 'New' Brand | Quantity for All Brand | Difference |
---|---|---|---|---|---|
2021/10/01 | New | A | 40 | 100 | 60 |
2021/10/01 | New | B | 10 | 90 | 80 |
2021/10/01 | New | C | 50 | 150 | 100 |
2021/10/01 | New | D | 30 | 200 | 170 |
这些是我的疑问:
查询1:
SELECT InvoiceDate, Brand, Region, Quantity From TotalSales // For All Brands
查询2:
SELECT InvoiceDate, Brand, Region, Quantity From TotalSales where Brand='New' // For New Brands
【问题讨论】:
第一个查询,根据定义,已经包含了第二个查询中的数据...第二个查询只是第一个带有WHERE
子句来过滤行的查询。因此,您是说要复制Brand
的值为'New'
的行吗?这不是您预期的结果。
其实,我的目标是只为新品牌获取过滤数据集(以便总数据集大小更小),我还可以获得该区域的总销售量以并排比较。
在预期结果集:“‘新’品牌的数量”和“所有品牌的数量”与“TotalSales”表中的“数量”基本相同
【参考方案1】:
有几种方法可以做到这一点... 首先-我认为您不希望结果中出现“品牌”列。这没有任何意义。另外,我想你会想要一个 AllBrands 总数的总和......
-
使用子查询
select allBrands.InvoiceDate, allBrands.Region, newBrands.Quantity as NewQuantity, allBrands.Quantity as allQuantity, allBrands.Quantity-newBrands.Quantity as Difference
FROM
(SELECT InvoiceDate, Region, SUM(Quantity) as Quantity From TotalSales GROUP BY InvoiceDate, Region) as allBrands
LEFT OUTER JOIN (SELECT InvoiceDate, Region, Quantity From TotalSales where Brand='New') as NewBrands ON NewBrands.InvoiceDate = allBrands.InvoiceDate AND NewBrands.Region = AllBrands.Region
或 2. 使用临时表
SELECT InvoiceDate, Region, SUM(Quantity) as Quantity INTO #allSales From TotalSales GROUP BY InvoiceDate, Region;
SELECT InvoiceDate, Region, Quantity INTO #newSales From TotalSales where Brand='New';
select allBrands.InvoiceDate, allBrands.Region, newBrands.Quantity as NewQuantity, allBrands.Quantity as allQuantity, allBrands.Quantity-newBrands.Quantity as Difference
FROM #allBrands allBrands
LEFT OUTER JOIN #newBrands newBrands ON NewBrands.InvoiceDate = allBrands.InvoiceDate AND NewBrands.Region = AllBrands.Region;
【讨论】:
嗨@CMGeek,感谢您的回答。我面临一个问题,例如,我们在 2021-08-02 、 2021-08-04 、 2021-08-07 有新品牌的销售(2021 年 8 月总共三天)但是我们有除新品牌以外的其他品牌的销售2021 年 8 月每天的品牌。所以当我们加入所有品牌和新品牌的发票日期时,所有品牌的总数量仅与新品牌的匹配发票日期一起获取。因此每个地区的总数量小于实际数量跨度> 您将需要使用 LEFT JOIN 而不是常规 JOIN。答案已编辑。【参考方案2】:您想获取brand = 'new' 的数量和所有品牌的总数量,然后比较两者。
实现此目的的一种方法是条件聚合:
select
invoicedate,
'New' as brand,
region,
sum(case when brand = 'New' then quantity else 0 end) as qty_new,
sum(quantity) as qty_all,
sum(quantity) - sum(case when brand = 'New' then quantity else 0 end) as diff
from totalsales
group by invoicedate, region
having sum(case when brand = 'New' then quantity else 0 end) > 0
order by invoicedate, region;
另一个是连接
with qnew as
(
select invoicedate, brand, region, quantity
from totalsales
where brand = 'New'
)
, qall as
(
select invoicedate, region, sum(quantity) as total
from totalsales
group by invoicedate, region
)
select
qnew.*, qall.total, qall.total- qnew.quantity as diff
from qnew
join qall on qall.invoicedate = qnew.invoicedate
and qall.brand = qnew.brand
and qall.region = qnew.region
order by qnew.invoicedate, qnew.brand, qnew.region;
【讨论】:
嗨@Thorsten,感谢您的回答。我面临一个问题,例如,我们在 2021-08-02 、 2021-08-04 、 2021-08-07 有新品牌的销售(2021 年 8 月总共三天)但是我们有除新品牌以外的其他品牌的销售2021 年 8 月每天的品牌。但是,这个带有条件聚合的查询仅从新品牌中获取匹配发票日期的“qty_all”行。因此,每个地区所有品牌的总数量小于实际数量 您在请求下的评论听起来就像您想要的那样:仅存在“新”条目的日期/地区。如果您还想要其他日期/地区,请删除HAVING
子句。对于第二个查询,您需要将内部连接更改为 from qall left outer join qnew on ...
并使用 COALESCE(qnew.quantity, 0)
将缺失的和设为零。【参考方案3】:
您可以对如下数据使用简单的条件聚合 (SUM
):
DECLARE @TotalSales TABLE (InvoiceDate DATE, Brand NVARCHAR(16), Region NCHAR(1), Quantity INT)
INSERT INTO
@TotalSales(
InvoiceDate,
Brand,
Region,
Quantity
)
VALUES ('10/1/2021', 'New', 'A', 20),
('10/1/2021', 'New', 'A', 20),
('10/1/2021', 'Old', 'A', 30),
('10/1/2021', 'Old', 'A', 30),
('10/1/2021', 'New', 'B', 10),
('10/1/2021', 'Old', 'B', 30),
('10/1/2021', 'Old', 'B', 50),
('10/1/2021', 'New', 'C', 50),
('10/1/2021', 'Old', 'C', 100),
('10/1/2021', 'New', 'D', 10),
('10/1/2021', 'New', 'D', 10),
('10/1/2021', 'New', 'D', 10),
('10/1/2021', 'Old', 'D', 100),
('10/1/2021', 'Old', 'D', 70),
('11/1/2021', 'Old', 'A', 50)
;WITH Data AS (
SELECT
ts.InvoiceDate,
ts.Region,
SUM(ts.Quantity) AS QuantityAll,
SUM(CASE WHEN ts.Brand = 'New' THEN ts.Quantity ELSE 0 END) AS QuantityNew
FROM
@TotalSales ts
GROUP BY
ts.InvoiceDate,
ts.Region
)
SELECT
d.InvoiceDate,
d.Region,
d.QuantityAll,
d.QuantityNew,
d.QuantityAll - d.QuantityNew AS TheDifference
FROM
Data d
ORDER BY
d.InvoiceDate,
d.Region
我使用了 CTE,这样我们就不必重复条件 SUM(CASE WHEN...
来在 QuantityNew
和 QuantityAll
之间进行减法。
输出是:
InvoiceDate Region QuantityAll QuantityNew TheDifference 2021-10-01 A 100 40 60 2021-10-01 B 90 10 80 2021-10-01 C 150 50 100 2021-10-01 D 200 30 170 2021-11-01 A 50 0 50
【讨论】:
以上是关于如何获得两个查询结果集之间的差异的主要内容,如果未能解决你的问题,请参考以下文章
如何在同一个表上组合两个查询以在 MySQL 中获得单个结果集