如何获得两个查询结果集之间的差异

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... 来在 QuantityNewQuantityAll 之间进行减法。

输出是:

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 中获得单个结果集

值列表与数据集的as.list之间的差异

将两个 SQL 查询的结果组合为单独的列

SQL语句对返回的结果集里的字段再进行条件查询,在一个结果集显示

可以通过查询结果获取结果集行数吗?

怎么分析关注的功能基因集在转录组结果中表现如何?