У меня есть поле для комментариев, используемое для хранения названия товара, проданного на сайте, а также номера ставки (bid_id). К сожалению, bid_id не хранится отдельно в этой таблице.

Например, я хочу запросить элементы, у которых число (bid_id) больше 4000.

Итак, что у меня есть:

select * from mysql_table_name where comment like '< 4000'

Я знаю, что это не сработает, но мне нужно что-то подобное, что работает.

Большое спасибо!

0
Duetschpire 27 Ноя 2016 в 03:37

3 ответа

Лучший ответ

Просто очистите свой столбец bid_id. Тогда index есть.

create table `prior`
(   id int auto_increment primary key,
    comments text not null
);
insert `prior` (comments) values ('asdfasdf adfas d d 93827363'),('mouse cat 12345678');
alter table `prior` add column bid_id int; -- add a nullable int column
select * from `prior`; -- bid_id is null atm btw
update `prior` set bid_id=right(comments,8); -- this will auto-cast to an int
select * from `prior`; 
+----+-----------------------------+----------+
| id | comments                    | bid_id   |
+----+-----------------------------+----------+
|  1 | asdfasdf adfas d d 93827363 | 93827363 |
|  2 | mouse cat 12345678          | 12345678 |
+----+-----------------------------+----------+

Создайте индекс:

CREATE INDEX `idxBidId` ON `prior` (bid_id); -- or unique index
1
Drew 27 Ноя 2016 в 01:18

Нет готового, что работало бы так.

Вы можете написать собственную функцию или загружаемый UDF, но это будет значительная работа, которая окажет значительное влияние на базу данных. Тогда вы можете запустить WHERE GET_BID_ID(comment) < 4000.

Что вы можете сделать проще, так это придумать какой-нибудь способ извлечения bid_id с помощью доступные строковые функции.

Например, если bid_id всегда находится в последних десяти символах, вы можете извлечь их и заменить все символы, не являющиеся цифрами, на nil. Остается только bid_id и то , которые можно сравнить.

Конечно, вам нужно сложное выражение с LENGTH(), SUBSTRING() и REPLACE(). Если bid_id находится между легко узнаваемыми разделителями, возможно, SUBSTRING_INDEX() вам больше подойдет.

Но еще лучше ... добавьте столбец INTEGER, инициализируйте его значением null, затем сохраните извлеченный bid_id. Или ноль, если вы уверены, что bid_id нет. Хранение данных в смешанном контексте - зло (и известный антипаттерн SQL). Как только у вас появится столбец, вы можете каждые несколько секунд выбирать небольшое количество элементов со значением new_bid_id по-прежнему NULL и подвергать их извлечению, тем самым постепенно изменяя базу данных без перегрузки системы.

На практике

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

SELECT commento FROM arti LIMIT 3;

+-----------------------------------------+
| commento                                |
+-----------------------------------------+
| This is the first comment 100 200 42500 |
| Another 7 Q 32768                       |
| And yet another 200 15 55332            |
+-----------------------------------------+

Итак, нам понадобятся последние символы:

SELECT SUBSTRING(commento, LENGTH(commento)-5) FROM arti LIMIT 3;
+-----------------------------------------+
| SUBSTRING(commento, LENGTH(commento)-5) |
+-----------------------------------------+
|  42500                                  |
|  32768                                  |
|  55332                                  |
+-----------------------------------------+

Это выглядит хорошо, но на самом деле это не так; перед идентификатором остался лишний пробел. Итак, 5 не работает, SUBSTRING начинается с 1. Независимо от того; мы просто используем 4.

... и мы закончили.

mysql> SELECT commento FROM arti WHERE SUBSTRING(commento, LENGTH(commento)-4) < 40000;
+-------------------+
| commento          |
+-------------------+
| Another 7 Q 32768 |
+-------------------+

mysql> SELECT commento FROM arti WHERE SUBSTRING(commento, LENGTH(commento)-4) BETWEEN 35000 AND 55000;
+-----------------------------------------+
| commento                                |
+-----------------------------------------+
| This is the first comment 100 200 42500 |
+-----------------------------------------+

Проблема в том, что у вас номер разной длины (например, 300 и 131072). Затем вам нужно взять кусок, достаточно большой для большего числа, и если число короткое, вы получите, возможно, «1 5 300» в вашем фрагменте. Здесь на помощь приходит SUBSTRING_INDEX: при захвате семи символов, от «131072» до «1 5 300», идентификатор всегда будет в последнем токене, разделенном пробелами .

В ЭТОМ ПОСЛЕДНЕМ СЛУЧАЕ , когда числа не одинаковой длины, вы столкнетесь с проблемой. Извлеченные идентификаторы вообще не являются числами - для MySQL это строки . Это означает, что они сравниваются в лексикографическом, а не числовом порядке; а «17534» считается меньше , чем «202», точно так же, как «Алиса» стоит перед «Бобом». Чтобы преодолеть это, вам нужно преобразовать строку как целое число без знака, что еще больше замедлит операции.

WHERE CAST( SUBSTRING(...) AS UNSIGNED) < 4000
1
LSerni 27 Ноя 2016 в 10:42
select * from mysql_table_name where substring(comment,start,length, signed integer) < 4000

Это сработает, но я предлагаю создать новый столбец и поместить в него значение ставки, а затем сравнить.

Чтобы обновить значение в новом столбце, вы можете использовать

update table set newcol = substring(comment,start,length)

Надеюсь, это поможет

1
HDJEMAI 27 Ноя 2016 в 01:28