从MySQL查询计算百分比
我正在努力寻找畅销书前五名 我计算畅销书前五名的想法是:从MySQL查询计算百分比,mysql,Mysql,我正在努力寻找畅销书前五名 我计算畅销书前五名的想法是: percentage = number_of_SUCCESS_transactions_each_book / total_number_transactions_each_book Fetch the result(book_id, percentage) sorted in DESC order, with a LIMIT of 5 为了便于理解,下面是包含数据的表的简单表示: tblPayments ----------- tr
percentage = number_of_SUCCESS_transactions_each_book / total_number_transactions_each_book
Fetch the result(book_id, percentage) sorted in DESC order, with a LIMIT of 5
为了便于理解,下面是包含数据的表的简单表示:
tblPayments
-----------
trans_id | book_id | payment_status | purchase_date
---------------------------------------------------
1 | 233 | SUCCESS | 2017-04-05
2 | 145 | FAILED | 2017-04-10
3 | 233 | FAILED | 2017-04-05
4 | 233 | SUCCESS | 2017-04-05
tblBooks
--------
book_id | book_name
-------------------
233 | My Autobiography
145 | How to learn English
201 | Finding Nemo
我将在特定日期查询这本畅销书前五名。例如,从2017-04-01
到2017-04-25
我期望的输出是这样的:
book_id | book_name | percentage
----------------------------------
233 | My Autobiography | 67
145 | How to learn English | 0
201 | Finding Nemo | 0
经过数小时的头脑风暴后,我想到的是:
SELECT b.`book_id`, (
(
( SELECT COUNT(*) FROM `tblPayments` WHERE `book_id` = b.`book_id` AND `payment_status` = 'SUCCESS' ) /
( SELECT COUNT(*) FROM `tblPayments` WHERE `book_id` = b.`book_id` )
) * 100.0 ) AS `percentage`
FROM `tblPayments` AS b
WHERE b.`purchase_date` BETWEEN '2017-04-01' AND '2017-04-25'
GROUP BY b.`book_id`
ORDER BY `percentage` DESC LIMIT 5
是否可以进一步改善?它会导致数据库中的任何性能问题吗
现在我在回我家的火车上。所以我是从平板电脑上写的,从我的脑海里。我将能够测试出来,当我回到家大约6小时的时间。所以我想同时在这里问一下
或者你有没有比这更好的方法的建议
多谢各位
编辑 感谢@草莓和@Stefano Zanini的回答 还有一个疑问。如果我用
tblBooks
加入tblBooks
以获取结果集中的book\u name
字段,可以吗
我的意思是,这个tblPayments
表应该有很多行。那么,加入
行吗?或者我应该在PHP中获取这5行,然后再进行一次查询,以获取这5本书的book\u name
?什么是有效的方法
DROP TABLE IF EXISTS transactions;
CREATE TABLE transactions
(transaction_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,book_id INT NOT NULL
,transaction_status VARCHAR(12) NOT NULL
,transaction_date DATE NOT NULL
);
INSERT INTO transactions VALUES
(1,233,'SUCCESS','2017-04-05'),
(2,145,'FAILED','2017-04-10'),
(3,233,'FAILED','2017-04-05'),
(4,233,'SUCCESS','2017-04-05');
SELECT book_id
, SUM(CASE WHEN transaction_status = 'success' THEN 1 ELSE 0 END)/COUNT(*) success_rate
FROM transactions
GROUP
BY book_id
+---------+--------------+
| book_id | success_rate |
+---------+--------------+
| 145 | 0.0000 |
| 233 | 0.6667 |
+---------+--------------+
我省略了一些琐碎的部分。您可以通过将用于百分比的内部查询替换为条件和来改进该查询:
SELECT b.`book_id`,
SUM(case when `book_id` = b.`book_id` AND `payment_status` = 'SUCCESS' then 1 end) /
COUNT(*) * 100.0 AS `percentage`
FROM `tblPayments` AS b
WHERE b.`purchase_date` BETWEEN '2017-04-01' AND '2017-04-25'
GROUP BY b.`book_id`
ORDER BY `percentage` DESC
LIMIT 5
编辑
解决您的新问题:不需要通过PHP进行第二次查询,您可以在一次查询中完成所有操作:
select t1.book_id, t2.book_name, t1.percentage
from (
SELECT b.`book_id`,
SUM(case when `book_id` = b.`book_id` AND `payment_status` = 'SUCCESS' then 1 end) /
COUNT(*) * 100.0 AS `percentage`
FROM `tblPayments` AS b
WHERE b.`purchase_date` BETWEEN '2017-04-01' AND '2017-04-25'
GROUP BY b.`book_id`
ORDER BY `percentage` DESC
LIMIT 5
) t1
join tblBooks t2
on t1.book_id = t2.book_id
这可能比在第一次查询中加入tblBooks
要快
SELECT b.`book_id`,
c.`book_name`,
SUM(case when `book_id` = b.`book_id` AND `payment_status` = 'SUCCESS' then 1 end) /
COUNT(*) * 100.0 AS `percentage`
FROM `tblPayments` AS b
JOIN `tblBooks` AS c
ON b.`book_id` = c.`book_id`
WHERE b.`purchase_date` BETWEEN '2017-04-01' AND '2017-04-25'
GROUP BY b.`book_id`
ORDER BY `percentage` DESC
LIMIT 5
但是如果我是你,我会自己做一些测试,看看性能是否真的有问题,在这种情况下,哪个查询更快。谢谢你的回答!谢谢你!关于结果集中是否包含
书名
,我还有一个小小的疑问。我已经用细节编辑了我的问题。请检查并让我知道你的建议。谢谢你谢谢你的回答!我很感激!关于结果集中是否包含书名
,我还有一个小小的疑问。我已经用细节编辑了我的问题。请检查并让我知道你的建议。谢谢你一个左撇子加入(合并)就可以了。@草莓谢谢。你能告诉我你建议在哪里使用coalesce
?是为了防止在SELECT(或者可能是外部查询的SELECT)中被0除错误;否则将返回NULL时返回0。