MySQL从另一个更新表,忽略重复项

标签 mysql

感谢您提前提供的所有帮助!

我有 2 个表:付款和 payment_options。付款在结账时设置,但通过 user_id 链接到 payment_options。

以下是付款示例:

# id,   user_id, order_id, subtotal, tax,  tip,  total, payment_method, payment_details
641481, 736471,  641851,   14.88,    1.32, 1.86, 8.06,  Credit Card,    ending in
641431, 109351,  641801,   10.54,    0.94, 1.32, 2.80,  Credit Card,    ending in
641381, 734171,  641751,   22.02,    1.95, 2.75, 26.72, Credit Card,    ending in
641351, 722321,  641711,   17.48,    1.55, 3.00, 22.03, Credit Card,    ending in
641201, 721511,  641581,   18.14,    1.61, 2.27, 22.02, Credit Card,    ending in

Payment_options 示例(示例信息、代币、cc_masked 等,全部组成年份):

# id,  user_id, cc_type, cc_token,            cc_masked,        cc_exp_month, cc_exp_year,
13371, 736471,  Visa,    fo7i-zr1w-9rsw-c6ty, XXXXXXXXXXXX3821,  7,            2015
9951,  109351,  Visa,    r3t6-co2i-i0ao-xz8d, XXXXXXXXXXXX9405,  4,            2016
9941,  734171,  Amex,    bd86-96t0-3j0g-a88g, XXXXXXXXXXX3004,   8,            2017
9931,  722321,  Maste,   o6ow-td7c-lfk0-b47e, XXXXXXXXXXXX5818,  1,            2016
9921,  721511,  Visa,    ysjp-5o4w-n3ls-y1ix, XXXXXXXXXXXX5297,  3,            2017

我想要完成的是将 cc_typecc_masked 合并到表 payment 中,如下所示:

# id,   user_id, order_id, subtotal, tax,  tip,  total, payment_method, payment_details
641481, 736471,  641851,   14.88,    1.32, 1.86, 8.06,  Credit Card,    Visa ending in 3821
641431, 109351,  641801,   10.54,    0.94, 1.32, 2.80,  Credit Card,    Visa ending in 9405
641381, 734171,  641751,   22.02,    1.95, 2.75, 26.72, Credit Card,    Amex ending in 3004
641351, 722321,  641711,   17.48,    1.55, 3.00, 22.03, Credit Card,    Master ending in 5818
641201, 721511,  641581,   18.14,    1.61, 2.27, 22.02, Credit Card,    Visa ending in 5297

出现的问题是有些人保存了多张卡片。由于 payment_options 允许使用非唯一的 user_id 。如果我从一个表直接更新到另一个表,其中 user_id = user_id,恐怕值会被覆盖。

select `id`, `user_id`, `name`, cc_type, cc_masked,
    (select count(*) 
    from payment_options
    where user_id = count_table.user_id
    group by `user_id`)
    as count
from payment_options as count_table having count > 1

这是结果:

# id,  user_id, cc_type, cc_masked,         count
15551, 736471,  Visa,    XXXXXXXXXXXX3821,  2
15741, 736471,  Visa,    XXXXXXXXXXXX5708,  2
15961, 510911,  Master,  XXXXXXXXXXXX3770,  2
16491, 510911,  Amex,    XXXXXXXXXXX3005,   2

如您所见,user_id = 736471 保存了多张 Visa 卡。 payments payment_options 只能通过 user_id 关联。

这让我相信我不能只按 1:1 更新表,而是需要某种子句来不更新 user_id 保存了多张卡的行,以避免错误更新

编辑:为了清楚起见。

根据@VMai,我将使用以下 MySQL 查询,只需发布​​以进行双重检查

    SELECT CONCAT(cc_type, ' ending in ', RIGHT(cc_masked, 4)) 
    FROM paymen_options
    WHERE payment_options.user_id NOT EXISTS = (
          SELECT payment_options.user_id, (SELECT COUNT (*)
                 FROM payment_options
                 WHERE payment_options.user_id = count_table.user.id
                 GROUP BY user_id)
                 AS count
            FROM payment_options as count_table
            HAVING count > 1
          )
    );

这看起来正确吗? Workbench 给我一个错误 1064 接近 NOT EXISTS,我现在正在尝试解决这个问题。

最佳答案

试试这个。无法测试,因此请运行数据库和备份的副本!

// uses PHP Database Objects (PDO) - will need adapting for use with mysqli instead
// add your host, database, username and password below
$db_connection = new PDO('mysql:host='. $DB_HOST .';dbname='. $DB_NAME . ';charset=utf8', $DB_USER, $DB_PASS);

$select_query  = 'SELECT user_id, CONCAT(cc_type, ' ending in ', RIGHT(cc_masked, 4)) AS cc,';
$select_query .= '(SELECT COUNT(*) FROM payment_options WHERE user_id = count_table.user_id GROUP BY `user_id`) AS count ';
$select_query .= 'FROM payment_options AS count_table HAVING count = 1';

// use LIMIT in SQL statement if large tables,
// otherwise your PHP script might timeout if you try to do too much

$SELECT = $db_connection->prepare($select_query);
$SELECT->execute();

$UPDATE = $db_connection->prepare('UPDATE payments SET payment_details=:payment_details WHERE user_id=:user_id');
$count = 0;
$success = true;

while($row = $SELECT->fetch(PDO::FETCH_ASSOC)) {
    $UPDATE->bindValue(':payment_details', $row['cc'], PDO::PARAM_STR);
    $UPDATE->bindValue(':user_id', $row['user_id'], PDO::PARAM_INT);
    $UPDATE->execute();

    if($UPDATE->errorCode() != 0) {
        echo "error: ".$UPDATE->errorInfo()[2]."<br><br>";
        $success = false;
        break;
    }
    $count++;
}
if($success)
    echo "<b>SUCCESS!<b>";
else
    echo "<b>FAILED!<b> (see error message above)";

echo "<br><br>Updated ".number_format($count)." rows!";

关于MySQL从另一个更新表,忽略重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25710579/

相关文章:

java - 计算两个 long/lat 之间的距离

php - 如何在给定经度和纬度的情况下从数据库获取到地点的距离

mysql - 使用指向同一个表的两个键创建 View ?

mysql - C API 用于连接 C & SQL 数据库

php - 从数据库中的交集行和列中选择一个价格

php - 使用 SQL 和 PHP 获取 MySQL 上的行数

MySQL 查询按属性过滤

mysql - Django - SQLite 与 MySQL 上的 DateTimeField 查询

Mysql 触发器或者只是一个简单的 Insert 语句..哪个更好地记录历史记录?

php - 尝试从 mysql 查询写入 Php fwrite XML 文件