0

我有一张这样设计的桌子:

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

这里的问题是,如何计算支付成功后支付失败的次数。所以这里的结果应该是这样的:

John Doe - 3 Failed Payment
Juan Dela Cruz - 2 Failed Payment

我希望你明白我在这里想要完成什么。

您的帮助将不胜感激和奖励!

谢谢!:)

4

4 回答 4

1

为了简洁明了,我将在我的代码中给一些东西起别名。

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

我有点生疏了,我没有测试过这个 SQL,但如果它不起作用,我怀疑是因为我的 " FROM Payments, <subquery>" 语法。我无法验证我的解决方案,因此如果它不起作用,您可能需要招募人员来帮助您。

如果你想知道,这是我的逻辑:

  1. 我的代码假设 PaymentIds 按时间顺序递增。
  2. 执行查询以获取每个用户(最里面的SELECT)最后一次成功付款的 ID。
  3. 重新查询 Payments 表以获取COUNT每个用户的行数,这些行位于最内层检索到的“最后一次成功的付款 ID”值之后SELECT
  4. JOIN步骤 3 的结果与用户表一起获取用户名。

另外,关于未来数据库设计的一些提示:没有必要在数据库设计中使用匈牙利符号——每次看到“tbl_”前缀时我都会畏缩。我还建议不要将主键字段简单地命名为“id”,因为这会使 JOIN 变得更加困难,因为您需要消除它们的歧义。考虑在它们前面加上表的名称(例如“ payments.id”变成“ Payments.PaymentId”)。

于 2013-01-30T03:48:31.070 回答
1

尝试使用 count 函数和 group by 语句

例如:

select Name, count(Status), Status from tbl_User as tu, tbl_User_Payment as tup where tup.user_id = tu.id group by status

检查一下,让我知道这是否有帮助。

于 2013-01-30T03:51:25.967 回答
1

试试这个查询

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`;
于 2013-01-30T03:55:05.273 回答
-1

PHP 版本。这可以进行优化,使其不会遍历表user中的每个 / 行tbl_User,但它可以完成工作。

<?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();

?>
于 2013-01-30T04:13:51.680 回答