简体   繁体   中英

MySQL count result

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:

  1. My code works in the assumption that PaymentIds are incremented sequentially chronologically.
  2. Do a query that gets the ID of the last successful payment, per user (the innermost SELECT ).
  3. Re-query the Payments table to get the COUNT of rows, per user, that come after the "last successful payment ID" values that were retrieved by the innermost SELECT .
  4. 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.

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