SQL 通过合并 2 个表来查询每天售出的图书总数?

SQL query to find the total number of books sold for each day by merging 2 tables?

我正在尝试查找 product_idtxn_day 的图书总销量(数量总和)。我有 2 个表,transactionscatalog,如下所示:

Table 1: transaction

market_id, txn_day, customer_id, product_id, quantity
1,2019-03-01,1,B0002,1
1,2019-03-01,2,B0003,1
1,2019-03-01,1,B0001,1
3,2019-03-01,3,B0001,1
3,2019-03-01,4,B0002,1
4,2019-03-01,1,B0002,1
4,2019-03-01,5,B0001,1
4,2019-03-01,6,B0001,1

Table 2: catalog

market_id, product_id, title_name
1,B0001, Harry Potter 1
1,B0002, Harry Potter 2
1,B0003, Harry Potter 3
3,B0001, Harry Potter 1
3,B0002, Harry Potter 2
3,B0003, Harry Potter 3
4,B0001, Harry Potter 1
4,B0002, Harry Potter 2
4,B0003, Harry Potter 3

我编写了以下查询并获得了 product_id 的图书总销量(数量总和):

SELECT 
    transaction.txn_day, transaction.product_id,
    SUM(quantity) AS quantity 
FROM 
    transaction
GROUP BY
    transaction.product_id, transaction.txn_day;

我尝试通过以下查询为每个 product_id 获取 title_name,但它似乎不正确。

SELECT 
    transaction.txn_day, transaction.product_id, catalog.title_name,
    SUM(quantity) AS quantity 
FROM 
    catalog
INNER JOIN 
    transaction ON catalog.product_id = transaction.product_id
GROUP BY
    transaction.txn_day, transaction.product_id, catalog.title_name;

我得到以下结果:

|txn_day    |product_id |title_name     |quantity
|2019-03-01 |B0002      |Harry Potter 2 |9
|2019-03-01 |B0001      |Harry Potter 1 |12
|2019-03-01 |B0003      |Harry Potter 3 |3

我希望结果类似于:

|txn_day    | product_id | quantity | title_name
|2019-03-01 | B0003      | 1        | Harry Potter 3
|2019-03-01 | B0002      | 3        | Harry Potter 2
|2019-03-01 | B0001      | 4        | Harry Potter 1

请提出查询所需的任何更改。

这是错误的,因为 product_id 和 title_name 在目录中不是唯一的。考虑:

SELECT transaction.txn_day, transaction.product_id, title_name,
sum(quantity) as qty FROM (SELECT DISTINCT product_id, title_name FROM catalog) AS cat
INNER JOIN transaction ON cat.product_id=transaction.product_id
group by transaction.txn_day, transaction.product_id, catalog.title_name;

此外,与本机字段名称相同的字段别名可能会在某些系统中引起问题,在 Access 中确实如此。

我认为您需要加入两个专栏,而不是一个专栏 -- 市场和产品:

SELECT t.txn_day, product_id, c.title_name, SUM(quantity) as quantity
FROM catalog c INNER JOIN
     transaction t
     USING (product_id, market_id)
GROUP BY t.txn_day, product_id, c.title_name;

这使用 USING 子句来简化 JOIN 条件。它还引入了 table 别名,因此查询更易于编写和阅读。

您的数据表明 product_idtitle_name 的关键。所以:

SELECT t.*, c.title_name
FROM  (
   SELECT txn_day, product_id, sum(quantity) AS sum_quantity
   FROM   transaction
   GROUP  BY txn_day, product_id
   ) t
LEFT   JOIN (
   SELECT DISTINCT product_id, title_name
   FROM   catalog
   ) c USING (product_id);

你真的应该有一个 table product 列出不同的产品。
(除非您的示例数据具有误导性,并且只有组合 (market_id, product_id) 是唯一的 - 在这种情况下,在聚合中省略 market_id 是没有意义的。因此我回到了我的第一个假设。)

除此之外,我使用子查询 SELECT DISTINCT product_id, title_name FROM catalog 即时得出 table。

如果在 table catalog.[=22= 中找不到 product_id

LEFT JOIN 而不仅仅是 JOIN 是一种防止删除行的保险]

此外,先聚合然后加入通常更便宜。参见:

  • Query with LEFT JOIN not returning rows for count of 0

我加载了您的数据并得到了以下结果:

DATE        ID      TITLE           QTY
3/1/2019    B0002   Harry Potter 2  9
3/1/2019    B0003   Harry Potter 3  3
3/1/2019    B0001   Harry Potter 1  12

这里关于错误的线索是每条记录的数量多了 3 倍。

如果您查看您的 INNER JOIN,您只是通过 product_id 加入。

查看您的交易行。

您可以看到每个 product_id 与 3 个不同的 market_ids 一起存在,这就是为什么您的数量增加了三倍。

解决方法: 将 market_id 添加到 JOIN:

SELECT   t.txn_day
        ,t.product_id
        ,c.title_name
        ,SUM(quantity) AS quantity
FROM     catalog c
         INNER JOIN transactions t ON c.product_id = t.product_id AND c.market_id = t.market_id
GROUP BY t.txn_day, t.product_id, c.title_name
order by c.title_name;

您将得到结果:

3/1/2019    B0001   Harry Potter 1  4
3/1/2019    B0002   Harry Potter 2  3
3/1/2019    B0003   Harry Potter 3  1