简体   繁体   English

如何在我的 sql 结果中包含分组的子查询?

[英]How do I include a grouped subquery in my sql result?

I have a display table that churns out daily result in the form of mysql.我有一个显示表,它以 mysql 的形式生成每日结果。 The daily result does not include products that are not making any sales today.每日结果不包括今天没有进行任何销售的产品。 How do i read from the table and determine to list all products even if a particular product is not making a sale that particular day but exists on the table on another day.我如何从表格中读取并确定列出所有产品,即使特定产品在特定日期没有销售但在另一天存在于表格中。

I researched and understand that using EXIST on the WHERE clause works.我研究并理解在WHERE子句上使用EXIST是有效的。 But i tried but to no avail.但我尝试过但无济于事。 I think I just have to include a grouped sub query inside a query but where should i put it.我想我只需要在查询中包含一个分组的子查询,但我应该把它放在哪里。 Below is an example of my code下面是我的代码示例

SELECT 
transaction.transactionservicetype AS Services,
COUNT(transaction.transactionid) AS Count,
IFNULL (SUM(transaction.transactionamount),'0') AS Amount,
IFNULL (SUM(statement.statementdebit),'0') AS NetCost,
IFNULL((SUM(transaction.transactionamount) - SUM(statement.statementdebit)),'0') as TotalEarning
FROM transaction
RIGHT JOIN statement ON transaction.transactionid = statement.transactionid
WHERE transaction.transactiondate = '2019-04-03' AND transaction.transactionstatus = 'SUCCESS' 
GROUP BY `transaction`.transactionservicetype ASC

Instead of displaying the table such as this:而不是显示这样的表格:

Services   Count   Amount   Netcost   Total Earning

Chicken   4       5.30       5.14           -

Beef      3       3.30       3.13          -

I want the result to include products not found on the same day but determine another type of products had existed on the table thus displaying the result as such:我希望结果包括在同一天找不到的产品,但确定表格中存在另一种类型的产品,从而显示结果:

Services   Count   Amount   Netcost   Total Earning

Chicken        4   5.30        5.14       -

Beef           3   3.30        3.13       -

Venison        0     0           0        -

Fowl           0     0           0        -

Update:更新:

I did not get the correct outcome using anti join and the other results.我没有使用 anti join 和其他结果得到正确的结果。 Scanning thru and using Ultimater's code as an example, this is as close to what i'd like to get from the result using sql query:扫描并使用 Ultimater 的代码作为示例,这与我想从使用 sql 查询的结果中获得的结果非常接近:

(
SELECT 
  transaction.transactionservicetype AS Services,
  COUNT(transaction.transactionid) AS Count,
  IFNULL (SUM(transaction.transactionamount),'0') AS Amount,
  IFNULL (SUM(statement.statementdebit),'0') AS NetCost,
  IFNULL((SUM(transaction.transactionamount) - SUM(statement.statementdebit)),'0') as TotalEarning
FROM
  transaction RIGHT JOIN statement
ON
  transaction.transactionid = statement.transactionid
WHERE
  transaction.transactiondate = '2019-04-03' AND transaction.transactionstatus = 'SUCCESS' 
GROUP BY
  `transaction`.transactionservicetype ASC
)
UNION
(
SELECT 
  transactionservicetype AS Services,
    '0' AS Count,
    '0' AS Amount,
  '0' AS NetCost,
  '0' AS TotalEarning
FROM
  transaction
GROUP BY
  transactionservicetype ASC
)

The above sql query got me a bit closer to what I wanted from my outcome.上面的 sql 查询让我更接近我想要的结果。 And this is the result:这是结果:

Services   Count   Amount   Netcost   Total Earning

Chicken        4   5.30        5.14       -

Beef           3   3.30        3.13       -

Chicken        0     0           0        -

Beef           0     0           0        -

Venison        0     0           0        -

Fowl           0     0           0        -

I just have to remove the duplicated rows (Chicken, Beef) how do i fix it using sql query?我只需要删除重复的行(Chicken, Beef)我如何使用 sql 查询修复它?

Untested but pretty sure you're looking for something like this:未经测试但很确定您正在寻找这样的东西:
The idea being you'd UNION ALL your current results onto an anti-join to get the remaining results to simulate a FULL JOIN :这个想法是你将所有当前的结果联合到一个反连接上以获得剩余的结果来模拟FULL JOIN

(
SELECT 
  transaction.transactionservicetype AS Services,
  COUNT(transaction.transactionid) AS Count,
  IFNULL (SUM(transaction.transactionamount),'0') AS Amount,
  IFNULL (SUM(statement.statementdebit),'0') AS NetCost,
  IFNULL((SUM(transaction.transactionamount) - SUM(statement.statementdebit)),'0') as TotalEarning
FROM
  transaction RIGHT JOIN statement
ON
  transaction.transactionid = statement.transactionid
WHERE
  transaction.transactiondate = '2019-04-03' AND transaction.transactionstatus = 'SUCCESS' 
GROUP BY
  `transaction`.transactionservicetype ASC
)

UNION ALL

(
SELECT
  transaction.transactionservicetype AS Services,
  COUNT(transaction.transactionid) AS Count,
  IFNULL (SUM(transaction.transactionamount),'0') AS Amount,
  '0' AS NetCost,
  '0' as TotalEarning
FROM
  transaction LEFT JOIN statement
ON
  transaction.transactionid = statement.transactionid
WHERE
  statement.statementid IS NULL AND transaction.transactiondate = '2019-04-03' AND transaction.transactionstatus = 'SUCCESS'
GROUP BY
  `transaction`.transactionservicetype ASC
);

You could also leave off the transaction.transactiondate = '2019-04-03' AND transaction.transactionstatus = 'SUCCESS' on the anti-join depending on the criteria where you want to grab such "missing" services.您还可以根据您想要获取此类“缺失”服务的标准,在反加入中transaction.transactiondate = '2019-04-03' AND transaction.transactionstatus = 'SUCCESS'

The above also assumes transaction.transactionid is an existing column and a primary key.上面还假设transaction.transactionid是一个现有的列和一个主键。

The second part is the anti-join:第二部分是反连接:

SELECT
  transaction.transactionservicetype AS Services,
  COUNT(transaction.transactionid) AS Count,
  IFNULL (SUM(transaction.transactionamount),'0') AS Amount,
  '0' AS NetCost,
  '0' as TotalEarning
FROM
  transaction LEFT JOIN statement
ON
  transaction.transactionid = statement.transactionid
WHERE
  statement.statementid IS NULL AND transaction.transactiondate = '2019-04-03' AND transaction.transactionstatus = 'SUCCESS'
GROUP BY
  `transaction`.transactionservicetype ASC

You should be able to run this by itself and see results such as this:您应该能够自己运行它并看到如下结果:

Services   Count   Amount   Netcost   Total Earning

Venison        0     0           0        0

Fowl           0     0           0        0

I wrote the anti-join by changing the RIGHT JOIN to a LEFT JOIN, specifying statement.statementid IS NULL in the WHERE clause so you don't get any INNER JOIN data you already have from the previous query, and I adjusted the counting logic such as NetCost and TotalEarnings by hard-coding those since there'd be no matches for those in such an anti-join in order to speed up its logic.我通过将 RIGHT JOIN 更改为 LEFT JOIN 来编写反连接,在 WHERE 子句中指定statement.statementid IS NULL这样您就不会从上一个查询中获得任何 INNER JOIN 数据,并且我调整了计数逻辑例如 NetCost 和 TotalEarnings 通过硬编码它们,因为在这种反联接中没有匹配项,以加快其逻辑。

Using an anti-join for the purposes of simulating a full join in MySQL is covered in this answer here:此处的答案中介绍了使用反联接来模拟 MySQL 中的完全联接:
https://stackoverflow.com/a/4796911/466314 https://stackoverflow.com/a/4796911/466314

An anti-join is a term used in the post I linked to, but not really an official term.反加入是我链接到的帖子中使用的一个术语,但不是真正的官方术语。 The term "anti" here means there needs to be an original join, then you want to do another join but grab the inverse of that join when masked to a full join.此处的术语“反”意味着需要有一个原始连接,然后您想要进行另一个连接,但在屏蔽为完全连接时获取该连接的反向连接。 This is different from merely combining the results of a LEFT and RIGHT (outer) join with each other because they share the same INNER JOIN data and you'd have redundant results.这与仅仅将 LEFT 和 RIGHT(外部)连接的结果相互组合不同,因为它们共享相同的 INNER JOIN 数据并且您将获得冗余结果。

A UNION ALL allows that sort of redundancy. UNION ALL允许这种冗余。 A UNION by itself removes those duplicates. UNION本身会删除这些重复项。

If you want to rely upon UNION to remove those duplicates, you can simulate an easier to understand FULL JOIN like so:如果您想依靠 UNION 来删除这些重复项,您可以模拟一个更容易理解的 FULL JOIN,如下所示:

(
SELECT 
  transaction.transactionservicetype AS Services,
  COUNT(transaction.transactionid) AS Count,
  IFNULL (SUM(transaction.transactionamount),'0') AS Amount,
  IFNULL (SUM(statement.statementdebit),'0') AS NetCost,
  IFNULL((SUM(transaction.transactionamount) - SUM(statement.statementdebit)),'0') as TotalEarning
FROM
  transaction RIGHT JOIN statement
ON
  transaction.transactionid = statement.transactionid
WHERE
  transaction.transactiondate = '2019-04-03' AND transaction.transactionstatus = 'SUCCESS' 
GROUP BY
  `transaction`.transactionservicetype ASC
)

UNION

(
SELECT 
  transaction.transactionservicetype AS Services,
  COUNT(transaction.transactionid) AS Count,
  IFNULL (SUM(transaction.transactionamount),'0') AS Amount,
  IFNULL (SUM(statement.statementdebit),'0') AS NetCost,
  IFNULL((SUM(transaction.transactionamount) - SUM(statement.statementdebit)),'0') as TotalEarning
FROM
  transaction LEFT JOIN statement
ON
  transaction.transactionid = statement.transactionid
WHERE
  transaction.transactiondate = '2019-04-03' AND transaction.transactionstatus = 'SUCCESS' 
GROUP BY
  `transaction`.transactionservicetype ASC
);

All I did was wrote the same original query again but changed the term RIGHT to LEFT, and put them between a UNION to remove duplicates when joining the results together.我所做的只是再次编写相同的原始查询,但将术语 RIGHT 更改为 LEFT,并将它们放在 UNION 之间以在将结果连接在一起时删除重复项。

Edit:编辑:

Here's the latest suggestion: Use the original query, but change from a RIGHT JOIN to a LEFT JOIN, then move the entire WHERE clause to the ON clause.这是最新的建议:使用原始查询,但从 RIGHT JOIN 更改为 LEFT JOIN,然后将整个 WHERE 子句移动到 ON 子句。

SELECT 
  transaction.transactionservicetype AS Services,
  COUNT(transaction.transactionid) AS Count,
  IFNULL (SUM(transaction.transactionamount),'0') AS Amount,
  IFNULL (SUM(statement.statementdebit),'0') AS NetCost,
  IFNULL((SUM(transaction.transactionamount) - SUM(statement.statementdebit)),'0') as TotalEarning
FROM
  transaction LEFT JOIN statement
ON
  transaction.transactionid = statement.transactionid AND
  transaction.transactiondate = '2019-04-03' AND
  transaction.transactionstatus = 'SUCCESS' 
GROUP BY
  `transaction`.transactionservicetype ASC

As per the results given to me, we can modify the almost attempt and merely do a subquery on the results, and a group by to get the desired output:根据给我的结果,我们可以修改几乎尝试,只需对结果进行子查询,然后分组即可获得所需的输出:

SELECT r.Services as 'Services',SUM(r.Count) as 'Count', SUM(r.Amount) as 'Amount',SUM(r.NetCost) as 'NestCost', SUM(r.TotalEarnings) AS 'TotalEarnings'
FROM
(
    SELECT 
      transaction.transactionservicetype AS Services,
      COUNT(transaction.transactionid) AS Count,
      IFNULL (SUM(transaction.transactionamount),'0') AS Amount,
      IFNULL (SUM(statement.statementdebit),'0') AS NetCost,
      IFNULL((SUM(transaction.transactionamount) - SUM(statement.statementdebit)),'0') as TotalEarning
    FROM
      transaction RIGHT JOIN statement
    ON
      transaction.transactionid = statement.transactionid
    WHERE
      transaction.transactiondate = '2019-04-03' AND transaction.transactionstatus = 'SUCCESS' 
    GROUP BY
      `transaction`.transactionservicetype ASC

    UNION

    SELECT 
      transactionservicetype AS Services,
        '0' AS Count,
        '0' AS Amount,
      '0' AS NetCost,
      '0' AS TotalEarning
    FROM
      transaction
    GROUP BY
      transactionservicetype ASC
) r
GROUP BY r.Services;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM