2014-09-07 3 views
0

Спасибо за помощь!Таблица обновления MySQL от другого, игнорируя дубликаты

У меня есть 2 стола: платежи и платежи. Платежи устанавливаются во время проверки, но привязаны к payment_options через user_id.

Вот пример платежей:

# 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 (Sample Info, жетоны, 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_type и cc_masked в таблице payments так это выглядит:

# 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 имеет несколько карт, сохраненных во избежание ошибочных обновлений

EDIT: для ясности.

По @VMai Я буду работать со следующим MySQL Query, просто размещение перепроверить

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 около НЕ СУЩЕСТВУЮЩИХ, с которыми я сейчас пытаюсь сражаться.

+0

Я действительно пробовал, но я не понимаю, каким должен быть ваш желаемый результат. Пожалуйста, добавьте его. И добавьте несколько строк, чтобы можно было увидеть проблему с несколькими картами. – VMai

+0

Я только что обновил свой вопрос, чтобы уточнить, каким должен быть мой конечный результат. Спасибо. – Bardworx

+0

Вы используете PHP? Я мог бы помочь со сценарием. –

ответ

0

Попробуйте это. Не удалось протестировать, так что запустите копию своей базы данных и резервной копии!

// 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!"; 
+0

Я сделаю это ответом из-за вашей тяжелой работы, но я не хочу запускать ваш скрипт слепым, даже если он работает, поскольку я пытаюсь узнать немного больше. Спасибо, однако, поскольку это будет очень полезно в ближайшем будущем. – Bardworx

+0

Не беспокойтесь. Надеюсь, это поможет, и это то, что вы искали. Цените, что здесь происходит довольно много, но если вы работаете над кодом, вы должны выяснить, что происходит. Он использует два подготовленных заявления PDO: ** 1) ** ВЫБРАТЬ все user_ids и cc info, где есть только один способ оплаты (все остальные игнорируются; ** 2) ** UPDATE в цикле для обновления данных платежей с помощью информацию от SELECT. Дайте мне знать, если вам нужны какие-либо дополнительные разъяснения, иначе пошлите и отметьте как ответ :) –

Смежные вопросы