2015-03-08 4 views
1

У меня небольшая проблема с запросом php mysql, я ищу помощь.mysql like query exclude numbers

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

id ancestors 
10 1,3,4,5 

Так человек ид 10 порожден идентификатором 5, который порожден идентификатором 4, который усыновил на 3 и т.д. ...

Теперь я хочу, чтобы выбрать все человек, которые имеют идентификатор x у их предков, поэтому запрос будет примерно таким: выберите * от людей, где такие предки, как «% x%»

Теперь это будет работать отлично, за исключением того, что если id x позволяет сказать 2, а запись имеет id предка 32, этот запрос будет извлекать 32, потому что 32 содержит 2. И если я использую «%, x,%» (включая запятые), запрос будет игнорировать записи, чей предок x находится на любом ребре (слева или справа) столбца. Он также будет игнорировать записи, чей х является единственным предком, поскольку никакие запятые не присутствуют.

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

Спасибо.

Редактировать: Хорошо, ребята, помогите мне придумать лучшую схему.

+0

Вы столкнулись с плохим дизайном базы данных. Вы никогда не сможете заставить это работать последовательно или легко запросить. Вам нужно остановиться и сделать некоторое чтение о том, как создать отношения один-много, используя реляционную базу данных. Просто сделайте google и искупайтесь в полученных знаниях – RiggsFolly

+2

Вы должны прочитать это: http://stackoverflow.com/questions/3653462/is-storing-a-delimited-list-in-a-database-column-really-that- bad –

+0

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

ответ

2

Вы не храните ваши данные надлежащим образом. В любом случае, если вы все еще хотите использовать эту схему, вы должны использовать FIND_IN_SET вместо LIKE, чтобы избежать нежелательных результатов.

SELECT * 
    FROM mytable 
WHERE FIND_IN_SET(2, ancestors) <> 0 
+1

Ничего себе, пять ответов и правильно решает проблему. –

1

Необходимо пересмотреть структуру базы данных. Добавить новую таблицу «предков» в базе данных со столбцами:

id id_person ancestor 
1 10  1 
2 10  3 
3 10  4 

После - использование JOIN запрос с «WHERE IN», чтобы выбрать правильные строки.

+0

Это не совсем правильно. – Strawberry

+0

Я открыт для лучших предложений Stawberry, даже при изменении схемы, так что стреляйте. –

0

Вы можете хранить свои ценности как массив JSON

id | ancestors 
10 | {"1","3","4","5"} 

и затем запрос следующим образом:

$query = 'select * from people where ancestors like \'%"x"%\''; 

Лучше, конечно, с помощью таблицы отображения для вашего многие-ко-многим отношение

1

У вас возникла эта проблема из-за неправильного дизайна базы данных. Первые DB-базы данных, основанные на СУБД, не предназначены для такого рода данных, а на основе диаграмм db скорее всего подходят для такого решения.

Если в нем содержится небольшое количество данных, вы можете использовать mysql, но дизайн все еще не прав, если вы заботитесь только об их «отце», а затем просто добавьте столбец для персоны (или как бы вы его называете). если его null - не имеет отца/неизвестного в противном случае - содержит (int) его родителя.

Если вам нужно больше, чем просто отношения «отец», вы можете использовать pivot table, чтобы содержать отношения двух человек, но это не простая задача.

+0

Я не думаю, что это точно сказать, что СУБД не предназначены для данных такого типа. Другие решения могут сделать это более эффективно/эффективно, но правильно спроектированная СУБД должна иметь возможность обрабатывать большое количество иерархических записей. – mesch

+0

Если он менее эффективен, то он не предназначен для этого .. Я не знаю, в чем цель этого генеалогического древа, но если вы попытаетесь создать многосемейное дерево генеалогии, вы в конечном итоге ожидаете, по крайней мере, пару секунд, чтобы получить дерево – Gal

0

Вы можете сделать это с помощью регулярных выражений:

SELECT * FROM mytable WHERE name REGEXP ',?(x),?' 

где х ваш поиск значение

+0

Я не уверен, что это совершенно правильно – Strawberry

+0

Почему? Я тестировал его в примерной базе данных mysql (5.5), кажется, что он работает правильно – keversc

+0

Я тестировал его, ища идентификатор 3, он извлекал строки, содержащие id 37 –

0
DROP TABLE IF EXISTS my_table; 

CREATE TABLE my_table 
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY 
,ancestors VARCHAR(250) NOT NULL 
); 

INSERT INTO my_table VALUES(10,',1,3,4,5'); 

SELECT * 
    FROM my_table 
WHERE CONCAT(ancestors,',') LIKE '%,5,%'; 
+----+-----------+ 
| id | ancestors | 
+----+-----------+ 
| 10 | ,1,3,4,5 | 
+----+-----------+ 

SELECT * 
    FROM my_table 
WHERE CONCAT(ancestors,',') LIKE '%,4,%'; 
+----+-----------+ 
| id | ancestors | 
+----+-----------+ 
| 10 | ,1,3,4,5 | 
+----+-----------+ 
1

Есть несколько установленных способов хранения иерархических данных в РСУБД. Я нашел это слайд-шоу, чтобы быть очень полезным в прошлом:

Models for Hierarchical Design

Так как сделки данных с родословной - и, следовательно, вы не ожидали бы это изменить, что часто - таблица закрытия может приспосабливать счет ,

Независимо от выбранной вами модели, обязательно осмотритесь и посмотрите, не выполнил ли кто-нибудь еще ее.

+0

Так что, видимо, мое является перечислением пути –