Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从MySQL查询计算百分比_Mysql - Fatal编程技术网

从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。