2012-04-10 2 views
0

У меня есть таблица со столбцом, содержащая список предков, отформатированных так: «1/12/45». 1 - корень, 12 - дети 1 и т. Д.sql in clause не работает

Мне нужно найти все записи, имеющие определенный узел/число в их списке предков. Для этого я написал SQL заявление:

select * from nodes where 1 in (nodes.ancestry) 

Я получаю следующее заявление об ошибке: оператор не существует: число = текст

Я попытался это так:

select * from nodes where '1' in (nodes.ancestry) 

но возвращает только записи, имеющие 1 в поле их происхождения. Не тот, который имеет, например, 1/12/45

Что случилось?

Спасибо!

+2

Что заставило вас думать, что 'в' является правильным инструментом для эта работа? Или что это волшебным образом знает, как интерпретировать ваш столбец 'ancestry'? –

+0

Если у вас есть возможность переделать свои таблицы, вы должны. Сохранение структурированной информации в таких строках не рекомендуется, и вы получите только все проблемы. – barsju

ответ

2

Это звучит как работа для LIKE, не IN.

Если мы предположим, что вы хотите найти это значение в любом положении, и тогда мы могли бы попробовать:

select * from nodes where '/' + nodes.ancestry + '/' like '%/1/%' 

Обратите внимание, что точный синтаксис для конкатенации варьируется между продуктами SQL. Обратите внимание, что я добавляю и добавляю к столбцу ancestry, так что нам не нужно рассматривать первые/последние элементы в списке иначе, чем средние. Заметим также, что мы окружаем 1/ s, так что мы не получаем ложных совпадений, например. с /51/ или /12/.

+0

Если ему нужно совместить '1 /', ему может понадобиться некоторое регулярное выражение. – barsju

+0

Привет, Дэмиен, ваше решение - это то, что я использовал до тех пор, пока не узнаю, но я хотел иметь что-то более чистым. IN казался мне очевидным, но это явно не очевидно ... – ndemoreau

+0

Для полноты: в Postgres это становится: select * из узлов, где '/' || Узлы. '/' like '%/1 /%' – ndemoreau

0

В MySQL вы можете написать:

SELECT * FROM nodes 
WHERE ancestry = '1' 
    OR LEFT(ancestry, 2) = '1/' 
    OR RIGHT(ancestry, 2) = '/1' 
    OR INSTR(ancestry, '/1/') > 0 
0

Оператор in ожидает разделенный запятыми список значений, или результат запроса, то есть:

... in (1,2,3,4,5) 

или:

... in (select id from SomeOtherTable) 

Что вам нужно сделать, это создать строку из номер, чтобы вы могли искать его в другой строке.

Просто поиск строки '1' в списке предков даст ложные срабатывания, так как он найдет ее в строке '2/12/45'. Вам нужно добавить разделитель в начале и в конце обеих строк, так что вы смотрите на строку, как '/1/' в строке как '/1/12/45/':

select * from nodes 
where charindex('/' + convert(varchar(50), 1) + '/', '/' + nodes.ancestry + '/') <> 0 
+0

Я также пробовал это: выберите * из узлов, где '1' in (replace (nodes.ancestry, '/', ',')), но я получаю тот же результат – ndemoreau

+0

@ndemoreau: Вы не можете использовать оператор 'in' для поиска строки в другой строке. Если вы хотите использовать оператор 'in', вам придется разбить строку« 1/12/45'' на три записи во временной таблице, что будет очень медленным решением. – Guffa

+0

Я понимаю это, но почему я не могу использовать оператор IN для поиска целого числа в список, разделенный запятыми. Это должно работать !? Не так ли? – ndemoreau