2015-01-16 5 views
0

У меня есть таблица ниже, моя проблема в том, как я могу обновить столбец в mysql на основе параметра.обновить столбец на основе значения, php mysql

+---+------------+-------------+ 
| id|  A  |  B  | 
+---+------------+-------------+ 
| 1 | a b a a |    | 
| 2 | b c a  |    | 
| 3 | b d c  |    | 
| 4 | a   |    | 
+---+------------+-------------+ 

Ожидаемые результаты должны подсчитывать количество вхождений «a», а затем обновлять столбец B., как показано ниже. точно мне нужно использовать регулярное выражение для подсчета количества «в»

+---+------------+-------------+ 
| |  A  |  B  | 
+---+------------+-------------+ 
| 1 | a b a a |  3  | 
| 2 | b c a  |  1  | 
| 3 | b d c  |  0  | 
| 4 | a   |  1  | 
+---+------------+-------------+ 
+5

Вы ищете для ответа только с помощью MySQL Или может PHP участвовать – Guillermo

+1

какие усилия? вы сделали? –

+0

Это поможет вам http://stackoverflow.com/q/14157480/1357033 –

ответ

1

Это может быть сделано в одном выражении SQL. (К сожалению, этот подход не удовлетворяет требованию использовать регулярные выражения. EDIT: см. Последующее описание для неэлегантного и неэффективного подхода, который использует регулярные выражения.)

Мы можем получить количество вхождений символов ' а»в колонке A и установить колонку B к графу, с запросом, как это:

UPDATE mytable t 
    SET t.B = (CHAR_LENGTH(t.A) - CHAR_LENGTH(REPLACE(t.A,'a',''))) 

Давайте распаковать, что немного. Это заявление UPDATE, нет предложения WHERE, поэтому мы собираемся получить доступ и, возможно, обновить каждую строку в mytable. (Мы назначаем псевдоним таблицы t. Это не требуется, но мы будем квалифицировать наши более поздние ссылки на столбцы A и B с использованием этого псевдонима, чтобы сделать его более понятным для кого-то, читающего инструкцию SQL, что это ссылки на столбцы в таблица.

на следующей строке, мы получили прямое SET положения, назначив значение столбца B.

Это следующее выражение, значение мы присваиваем в колонку B, что мы должны распаковать немного.

Чтобы рассчитать число 'a' символов, мы можем использовать небольшой трюк: мы знаем, что символ 'a' имеет ровно один символ в длину.

«Трюк» предназначен для использования функции REPLACE для поиска всех вхождений символа 'a' и их удаления (заменяя их нулевой длиной). Затем мы можем сравнить длины (количество символов) двух строк. Разница заключается в количестве символов 'a' в исходной строке.

В качестве демонстрации того, как работают эти выражения:

SELECT t.foo       AS foo 
    , REPLACE(t.foo,'a','')   AS foo_2 
    , CHAR_LENGTH(t.foo)     AS len 
    , CHAR_LENGTH(REPLACE(t.foo,'a','')) AS len_2 
    , CHAR_LENGTH(t.foo) - CHAR_LENGTH(REPLACE(t.foo,'a','')) AS `len-len_2` 
    FROM (SELECT 'a b a a' AS foo 
     UNION ALL SELECT 'b c a' 
     UNION ALL SELECT 'b c d' 
     UNION ALL SELECT 'a ' 
     ) t 

Возвращенный из этого запроса:

foo  foo_2  len len_2 len-len_2 
------- ------ ------ ------ --------- 
a b a a b   7  4   3 
b c a b c   5  4   1 
b c d b c d  5  5   0 
a      3  2   1 

Примечание: что возвращается в основном подсчет количества символов, которые были удален. Поэтому, если мы хотим подсчитать вхождения строки из нескольких символов, для примера: cat, нам нужно будет это учитывать.

Разделение возвращаемого значения на количество символов в cat было бы одним из способов сделать это. Или мы могли бы заменить строку cat строкой длиной в два символа, например. 'xx', поэтому разница в длине будет одним символом в каждом случае.


Followup

оригинальный вопрос, который задают, как считать 'а' символов с использованием регулярных выражений. Моя первая мысль заключалась в том, что это невозможно с MySQL REGEXP, потому что возврат от него равен NULL, 0 или 1. Но немного подумав об этом, это можно сделать, если мы рассчитываем на некоторое конечное число вхождений , Можно было бы проверить, если строка содержит, по меньшей мере, один «а» характер, это довольно просто:

'a b a a' REGEXP 'a' 

Это возвращает 1, если он совпадает, и 0, если он не делает. Также возможно проверить, содержит ли строка не менее двух символов 'a'. Это довольно простая задача:

'a b a a' REGEXP 'a.*a' 

Если мы складываем результат из двух выражений выше, мы могли бы получить количество либо 0, 1 или 2 для числа «а» символов.

Мы можем повторить тот же шаблон, чтобы увеличить его до 3, 4, 5 и т. Д. «A».

Это не изящно, и мы, конечно же, не хотим узнать, насколько теплый процессор будет делать все эти сравнения. Но он возвращает указанный результат, до некоторого конечного максимального значения. В этом примере шесть. (Строки, содержащие более шести «а» символов будет возвращать счетчик 6.

В качестве демонстрации:

SELECT t.foo 
    , (t.foo REGEXP CONCAT('.*',REPEAT('a.*',1))) 
     + (t.foo REGEXP CONCAT('.*',REPEAT('a.*',2))) 
     + (t.foo REGEXP CONCAT('.*',REPEAT('a.*',3))) 
     + (t.foo REGEXP CONCAT('.*',REPEAT('a.*',4))) 
     + (t.foo REGEXP CONCAT('.*',REPEAT('a.*',5))) 
     + (t.foo REGEXP CONCAT('.*',REPEAT('a.*',6))) 
     AS cnt_a 
    FROM (SELECT 'a b a a' AS foo 
     UNION ALL SELECT 'b c a' 
     UNION ALL SELECT 'b c d' 
     UNION ALL SELECT 'a ' 
     ) t 
0

Вариант 1: Чистый SQL

Заменить подстроку вы хотите считаться с пустой строкой. Сравнивая длину результирующей строки и исходную строку, вы можете сказать, сколько вхождений есть:

update table set b = (length(a) - length(replace(a,'a','')))/length('a') 

Вы можете заменить постоянную строку 'a' любой строки любой длины.

Вариант 2: Использование PHP и SQL

Вы можете перебрать все строки с PHP и использовать функцию substr_count для подсчета вхождений подстроки (в вашем случае подстрока будет «а»). Затем вы обновляете значение для b в этой строке. Предполагая, что поле id является основным ключом:

$query = $pdo->query("select id,a from table"); 
while($row = $query->fetch()) { 
    $b = substr_count($row['a']); 
    $id = $row['id']; 
    $pdo->query("update table set b = $b where id = $id"); 
} 

Обратите внимание, что этот подход не очень эффективен.

+0

Почему мы приводим примеры, в которых используется устаревший интерфейс mysql, нет ли уже достаточных примеров? Почему мы не приводим примеры используя mysqli или PDO? И мы надеемся, что на высоком небесах 'id' уникален, и это целочисленный тип, а не VARCHAR, если он содержит значение, подобное' '' OR 1 = 1'.Получение отдельных строк из таблицы и выдача отдельных операторов обновления - очень неэффективный подход к решению проблемы. – spencer7593

+0

Вы правы, спасибо за ваш комментарий. Я изменил свой ответ. Я перечислил вариант PHP, потому что это возможный подход, но не эффективный, но, как вы сказали, он работает. – Guillermo

+0

Преобразование в PDO приятно. В идеале мы хотели бы видеть как '$ b', так и' $ id', предоставленные в качестве аргументов привязки для подготовленного оператора; это образец, который мы привыкли видеть. Мы по-прежнему не видим в вопросе никакой гарантии, что столбец 'id' будет определен как не пустой (код PHP пропустит обновление этих строк), что он уникален (в противном случае PHP-код будет обновлять несколько строк, несколько раз), это не определено как тип символа и не содержит небезопасных значений (нам нужно было бы заключить значение $ id в одинарные кавычки и правильно избежать строки, чтобы сделать ее безопасной для включения в текст SQL. – spencer7593

0
UPDATE Table SET B = i.b 
FROM (SELECT LENGTH(A) - LENGTH(REPLACE(A, 'a', '')) as b from Table) i 
WHERE i.ID = Table.ID 
+0

Это достойный подход, но есть некоторые проблемы с реализацией: встроенное представление не возвращает столбец с именем 'id '; он не учитывает n umber символов 'a', и, кроме того, на самом деле нет необходимости в встроенном представлении. – spencer7593

+0

Очень хорошая идея, но она работает только в том случае, если подстрока для подсчета имеет длину '1'. – Guillermo

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