Reputation: 3869
I have a table with a column ancestry holding a list of ancestors formatted like this "1/12/45". 1 is the root, 12 is children of 1, etc...
I need to find all the records having a specific node/number in their ancestry list. To do so, I wrote this sql statement:
select * from nodes where 1 in (nodes.ancestry)
I get following error statement: operator does not exist: integer = text
I tried this as well:
select * from nodes where '1' in (nodes.ancestry)
but it only returns the records having 1 in their ancestry field. Not the one having for instance 1/12/45
What's wrong?
Thanks!
Upvotes: 0
Views: 508
Reputation: 700152
The in
operator expects a comma separated list of values, or a query result, i.e.:
... in (1,2,3,4,5)
or:
... in (select id from SomeOtherTable)
What you need to do is to create a string from the number, so that you can look for it in the other string.
Just looking for the string '1'
in the ancestry list would give false positives, as it would find it in the string '2/12/45'
. You need to add the separator to the beginning and the end of both strings, so that you look for a string like '/1/'
in a string like '/1/12/45/'
:
select * from nodes
where charindex('/' + convert(varchar(50), 1) + '/', '/' + nodes.ancestry + '/') <> 0
Upvotes: 0
Reputation: 239636
This sounds like a job for LIKE
, not IN
.
If we assume you want to search for this value in any position, and then we might try:
select * from nodes where '/' + nodes.ancestry + '/' like '%/1/%'
Note that exact syntax for string concatenation varies between SQL products. Note that I'm prepending and appending to the ancestry
column so that we don't have to treat the first/last items in the list differently than middle items. Note also that we surround the 1
with /
s, so that we don't get false matches for e.g. with /51/
or /12/
.
Upvotes: 2
Reputation: 57573
In MySQL you could write:
SELECT * FROM nodes
WHERE ancestry = '1'
OR LEFT(ancestry, 2) = '1/'
OR RIGHT(ancestry, 2) = '/1'
OR INSTR(ancestry, '/1/') > 0
Upvotes: 0