我有一个显示表,以mysql的形式显示每日结果。每日结果不包括今天没有任何销售的产品。我如何从表格中读取信息并确定列出所有产品,即使某个特定产品在该天没有销售但又在另一天出现在桌上。
我研究并了解,在EXIST
子句上使用WHERE
是可行的。但我试过,但无济于事。我想我只需要在查询中包括一个分组的子查询,但是我应该放在哪里。下面是我的代码示例
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
而不是显示诸如此类的表:
Services Count Amount Netcost Total Earning
Chicken 4 5.30 5.14 -
Beef 3 3.30 3.13 -
我希望结果中包含当天未找到的产品,但是确定表中还存在另一种产品,因此显示结果如下:
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 -
使用反连接和其他结果无法获得正确的结果。通过扫描并使用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
)
上面的sql查询使我更接近我想要的结果。结果就是这样:
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 -
我只需要删除重复的行(Chicken, Beef)
,如何使用sql查询修复它?
答案 0 :(得分:1)
未经测试但很确定您正在寻找类似这样的东西:
想法是,您将所有当前结果都联合到一个反联接上,以获取其余结果来模拟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
);
您还可以根据要获取此类“缺失”服务的条件,在反连接上放弃transaction.transactiondate = '2019-04-03' AND transaction.transactionstatus = 'SUCCESS'
。
以上内容还假设transaction.transactionid
是现有列和主键。
第二部分是反联接:
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
您应该能够自己运行它,并看到如下结果:
Services Count Amount Netcost Total Earning
Venison 0 0 0 0
Fowl 0 0 0 0
我通过将RIGHT JOIN更改为LEFT JOIN并在WHERE子句中指定statement.statementid IS NULL
来编写反联接,这样您就不会从上一个查询中获得任何INNER JOIN数据,因此我进行了调整计数代码(例如NetCost和TotalEarnings)通过对它们进行硬编码来进行编码,因为在这种反连接中没有匹配项可以加快其逻辑。
此答案涵盖了在MySQL中使用反联接以模拟完全联接的目的:
https://stackoverflow.com/a/4796911/466314
反连接是我链接到的帖子中使用的术语,但实际上不是官方术语。这里的“ anti”一词意味着需要有一个原始的联接,然后您想要进行另一个联接,但是当被屏蔽为完全联接时,要抓住该联接的相反方向。这不同于仅将LEFT和RIGHT(外部)联接的结果相互组合,因为它们共享相同的INNER JOIN数据,并且您将得到多余的结果。
UNION ALL
允许这种冗余。 UNION
本身会删除这些重复项。
如果您要依靠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
);
我所做的只是再次写了相同的原始查询,但是将RIGHT(权利)改为LEFT(左),并将它们放在UNION之间以在将结果连接在一起时删除重复项。
编辑:
这是最新的建议: 使用原始查询,但是从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
根据提供给我的结果,我们可以修改几乎尝试并仅对结果进行子查询,然后对结果进行分组以得到所需的输出:
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;