I have a table that is designed like this:
tbl_User
id
Name
tbl_User_Payment
id
user_id
amount
status
tbl_User
id Name
001 John Doe
002 Juan Dela Cruz
tbl_User_Payment
id user_id amount status
001 001 10 Successful
002 002 10 Fail
003 001 10 Fail
004 001 10 Fail
005 001 10 Fail
006 002 10 Successful
007 002 10 Fail
008 002 10 Fail
The problem here is that how can I count the number of Failed Payment after a Successful Payment. So the result here should be something like this:
John Doe - 3 Failed Payment
Juan Dela Cruz - 2 Failed Payment
I hope you understand what i'm trying to accomplish here.
Your help will be greatly appreciated and rewarded!
Thanks! :)
For brevity and clarity, I'm going to alias a few things in my code.
SELECT
Users.UserName,
FailCount
FROM
(
SELECT
UserId,
COUNT(*) As FailCount
FROM
Payments,
(
SELECT
UserId,
MAX( PaymentId ) As LastSuccessId
FROM
Payments
WHERE
Status = Successful
GROUP BY
UserId
) AS LastSuccess
WHERE
PaymentId > LastSuccessId
GROUP BY
UserId
) As FailCount
INNER JOIN Users ON Users.UserId = FailCount.UserId
ORDER BY
UserName DESC
I'm a bit rusty, I haven't tested this SQL but if it doesn't work I suspect it's because of my " FROM Payments, <subquery>
" syntax. I'm not in a position where I can verify my solution, so you might have to recruit someone to help you if it doesn't work.
If you're wondering, here's my logic:
SELECT
). COUNT
of rows, per user, that come after the "last successful payment ID" values that were retrieved by the innermost SELECT
. JOIN
the results from step 3 with the users table to get the usernames. Also, a few tips for future database design: there is no need to use Hungarian Notation in DB design - I cringe every time I see "tbl_" prefixes. I also advise against naming primary-key fields simply "id" as it makes JOINs more difficult as you need to disambiguate them. Consider prefixing them with the name of the table (eg " payments.id
" becomes " Payments.PaymentId
").
Try using the count function and the group by statement
for example:
select Name, count(Status), Status from tbl_User as tu, tbl_User_Payment as tup where tup.user_id = tu.id group by status
Check it out and let me know if this helps.
Try this query
SELECT
`user_id`,
COUNT(id) AS "Total",
SUM(CASE WHEN status= 'Fail' THEN 1 ELSE 0 END) AS "Failed",
SUM(CASE WHEN status= 'Successful' THEN 1 ELSE 0 END) AS "Successful"
FROM `tbl_User_Payment`
GROUP BY `user_id`;
The PHP version. This could be optimised so that it doesn't run through every user
/row in the tbl_User
table, but it gets the job done.
<?php
$mysqli = new mysqli('localhost', 'root', DB_PASSWORD, DB_NAME);
if ($mysqli->connect_error)
die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
$result = $mysqli->query("SELECT * FROM `tbl_User_Payment` WHERE `status` = 'Fail'"))
$array = [];
while ($col = $result->fetch_array(MYSQLI_ASSOC)) {
if (array_key_exists($col['user_id'], $array))
$array[$col['user_id']] = $array[$col['user_id']]+1;
else
$array[$col['user_id']] = 1;
}
$result->close();
$mysqli->close();
$mysqli = new mysqli('localhost', 'root', DB_PASSWORD, DB_NAME);
if ($mysqli->connect_error)
die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
$result = $mysqli->query("SELECT * FROM `tbl_User` WHERE 1"))
while ($col = $result->fetch_array(MYSQLI_ASSOC)) {
if (array_key_exists($col['id'], $array))
echo $col['Name'] . ' - ' . $array[$col['id']] . ' Failed attempts <br />';
}
$result->close();
$mysqli->close();
?>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.