I've got a database that manages files - some files contain/reference other files, and my goal is to design a query that can give me the whole "tree" for a given document.
For example the structure may look like this:
File 1
File 2
File 3
File 4
File 5
File 6
File 7
File 8
File 9
File 10
etc., where File 1 effectively contains all of the files following it
These are broken out in my database between two tables - lets call them the "Files" table and the "References" table
The "Files" table has information about the files themselves - FileID, Filename, etc.
The "References" table shows the relationship of the above structure using the FileIDs of the files. My issue is that, for example, File 6 is not referenced by File 1 - it is only referenced by File 5.
e.g.:
[ParentFileID] [ChildFileID]
1 2
1 3
1 4
1 5
5 6
5 7
5 8
8 9
8 10
Ideally I'd like to be able to check the position in the entire structure for any given FileID I pass in
Any ideas? I've been reading up on CTEs and it feels like some sort of recursive common table expression is what I'm after, though every example I can find is using one table and involves NULLs to track down the top level elements.
Yes, it can be done using a recursive CTE.
USE tempdb
GO
CREATE TABLE files
(
[file_id] int PRIMARY KEY,
[file_name] varchar(128) NOT NULL
);
INSERT INTO files VALUES
(1, 'File 1'),
(2, 'File 2'),
(3, 'File 3'),
(4, 'File 4'),
(5, 'File 5'),
(6, 'File 6'),
(7, 'File 7'),
(8, 'File 8'),
(9, 'File 9'),
(10, 'File 10');
CREATE TABLE [references]
(
parent_file_id int NOT NULL,
child_file_id int NOT NULL,
PRIMARY KEY (child_file_id)
);
INSERT INTO [references] VALUES
(1, 2),
(1, 3),
(1, 4),
(1, 5),
(5, 6),
(5, 7),
(5, 8),
(8, 9),
(8, 10);
GO
CREATE FUNCTION dbo.get_file_with_path(#file_id int)
RETURNS TABLE
AS
RETURN WITH h
AS
(
SELECT
f.file_id, f.file_id as child_file_id,
f.file_name, 0 as reverse_level,
CAST( '/' + f.file_name as varchar(8000)) as path
FROM
dbo.files f
WHERE
f.file_id = #file_id
UNION ALL
SELECT
h.file_id, r.parent_file_id as child_file_id,
h.file_name, h.reverse_level + 1 as reverse_level,
CAST('/' + f.file_name + h.path as varchar(8000)) as path
FROM
h
INNER JOIN [references] r
ON h.child_file_id = r.child_file_id
INNER JOIN dbo.files f
ON f.file_id = r.parent_file_id
)
SELECT TOP(1) h.file_id, h.file_name, h.path
FROM h
ORDER BY h.reverse_level DESC;
GO
SELECT *
FROM dbo.get_file_with_path(1)
UNION ALL
SELECT *
FROM dbo.get_file_with_path(3)
UNION ALL
SELECT *
FROM dbo.get_file_with_path(6)
UNION ALL
SELECT *
FROM dbo.get_file_with_path(10)
Output:
| file_id | file_name | path |
|---------|-----------|-------------------------------|
| 1 | File 1 | /File 1 |
| 3 | File 3 | /File 1/File 3 |
| 6 | File 6 | /File 1/File 5/File 6 |
| 10 | File 10 | /File 1/File 5/File 8/File 10 |
I assume you mean path when you say position
EDIT:
Answering the question in comments, you can also create a table valued function that returns the sub-tree below a given node:
CREATE FUNCTION dbo.get_file_subtree_excluding_self(#file_id int)
RETURNS TABLE
AS RETURN
WITH h AS
(
SELECT r.parent_file_id, r.child_file_id
FROM [references] r
WHERE r.parent_file_id = #file_id
UNION ALL
SELECT r.parent_file_id, r.child_file_id
FROM
h INNER JOIN [references] r
ON h.child_file_id = r.parent_file_id
)
SELECT h.child_file_id as [file_id]
FROM h
GO
SELECT * FROM dbo.get_file_subtree_excluding_self(5)
Output:
+---------+
| file_id |
+---------+
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
+---------+
The table references describes a graph. One node can have only one parent because of the primary key, but nothing prevents cycles. For example, consider the following data:
+-------+--------+
| child | parent |
+-------+--------+
| 1 | 2 |
| 2 | 3 |
| 3 | 1 |
+-------+--------+
As you can see, there are cycles on this graph.
Related
I have a table like this where i want to select all records except where two columns match certain values
id Signal_Type Input
1 Alarm 2
1 Alarm 4
1 Video 1
2 Alarm 4
2 Video 5
2 Alarm 7
I would like to select all records where ID = 1 and where Signal_Type != Alarm and Input != 2, but if both the Signal_Type and input arent matched then still show the record.
SELECT *
FROM ReceiverAlarms
WHERE id = '1' AND (Signal_Type != 'Alarm' AND Input != '2')
I expected this query to return
id Signal_Type Input
1 Alarm 4
1 Video 1
but instead it returns nothing.
Im sure there will be other questions on here asking for that but i wasnt sure how to word it to find what i wanted.
"if both the type and input arent matched then still show the record."
That's an OR
(Type != 'Alarm' OR Input != '2')
Below demo is for MySQL, but this will work for any DBMS
Schema (MySQL v5.7)
CREATE TABLE ReceiverAlarms (
`id` INTEGER,
`Type` VARCHAR(5),
`Input` INTEGER
);
INSERT INTO ReceiverAlarms
(`id`, `Type`, `Input`)
VALUES
(1, 'Alarm', 2),
(1, 'Alarm', 4),
(1, 'Video', 1),
(2, 'Alarm', 4),
(2, 'Video', 5),
(2, 'Alarm', 7);
Query #1
SELECT *
FROM ReceiverAlarms
WHERE id = '1' AND (Type != 'Alarm' OR Input != '2');
Output
| id | Type | Input |
| --- | ----- | ----- |
| 1 | Alarm | 4 |
| 1 | Video | 1 |
View on DB Fiddle
You can try below way -
select id, type,max(input) as input
from tablename
where id=1
group by id,type
I wonder why the BINARY_CHECKSUM function returns different result for the same:
SELECT *, BINARY_CHECKSUM(a,b) AS bc
FROM (VALUES(1, NULL, 100),
(2, NULL, NULL),
(3, 1, 2)) s(id,a,b);
SELECT *, BINARY_CHECKSUM(a,b) AS bc
FROM (VALUES(1, NULL, 100),
(2, NULL, NULL)) s(id,a,b);
Ouput:
+-----+----+------+-------------+
| id | a | b | bc |
+-----+----+------+-------------+
| 1 | | 100 | -109 |
| 2 | | | -2147483640 |
| 3 | 1 | 2 | 18 |
+-----+----+------+-------------+
-- -109 vs 100
+-----+----+------+------------+
| id | a | b | bc |
+-----+----+------+------------+
| 1 | | 100 | 100 |
| 2 | | | 2147483647 |
+-----+----+------+------------+
And for second sample I get what I would anticipate:
SELECT *, BINARY_CHECKSUM(a,b) AS bc
FROM (VALUES(1, 1, 100),
(2, 3, 4),
(3,1,1)) s(id,a,b);
SELECT *, BINARY_CHECKSUM(a,b) AS bc
FROM (VALUES(1, 1, 100),
(2, 3, 4)) s(id,a,b);
Ouptut for both first two rows:
+-----+----+------+-----+
| id | a | b | bc |
+-----+----+------+-----+
| 1 | 1 | 100 | 116 |
| 2 | 3 | 4 | 52 |
+-----+----+------+-----+
db<>fiddle demo
It has strange consequences when I want to compare two tables/queries:
WITH t AS (
SELECT 1 AS id, NULL AS a, 100 b
UNION ALL SELECT 2, NULL, NULL
UNION ALL SELECT 3, 1, 2 -- comment this out
), s AS (
SELECT 1 AS id ,100 AS a, NULL as b
UNION ALL SELECT 2, NULL, NULL
UNION ALL SELECT 3, 2, 1 -- comment this out
)
SELECT t.*,s.*
,BINARY_CHECKSUM(t.a, t.b) AS bc_t, BINARY_CHECKSUM(s.a, s.b) AS bc_s
FROM t
JOIN s
ON s.id = t.id
WHERE BINARY_CHECKSUM(t.a, t.b) = BINARY_CHECKSUM(s.a, s.b);
db<>fiddle demo2
For 3 rows I get single result:
+-----+----+----+-----+----+----+--------------+-------------+
| id | a | b | id | a | b | bc_t | bc_s |
+-----+----+----+-----+----+----+--------------+-------------+
| 2 | | | 2 | | | -2147483640 | -2147483640 |
+-----+----+----+-----+----+----+--------------+-------------+
but for 2 rows I get also id = 1:
+-----+----+------+-----+------+----+-------------+------------+
| id | a | b | id | a | b | bc_t | bc_s |
+-----+----+------+-----+------+----+-------------+------------+
| 1 | | 100 | 1 | 100 | | 100 | 100 |
| 2 | | | 2 | | | 2147483647 | 2147483647 |
+-----+----+------+-----+------+----+-------------+------------+
Remarks:
I am not searching for alternatives like(HASH_BYTES/MD5/CHECKSUM)
I am aware that BINARY_CHECKSUM could lead to collisions(two different calls produce the same output) here scenario is a bit different
For this definition, we say that null values, of a specified type,
compare as equal values. If at least one of the values in the
expression list changes, the expression checksum can also change.
However, this is not guaranteed. Therefore, to detect whether values
have changed, we recommend use of BINARY_CHECKSUM only if your
application can tolerate an occasional missed change.
It is strange for me that hash function returns different result for the same input arguments.
Is this behaviour by design or it is some kind of glitch?
EDIT:
As #scsimon
points out it works for materialized tables but not for cte.
db<>fiddle actual table
Metadata for cte:
SELECT name, system_type_name
FROM sys.dm_exec_describe_first_result_set('
SELECT *
FROM (VALUES(1, NULL, 100),
(2, NULL, NULL),
(3, 1, 2)) s(id,a,b)', NULL,0);
SELECT name, system_type_name
FROM sys.dm_exec_describe_first_result_set('
SELECT *
FROM (VALUES(1, NULL, 100),
(2, NULL, NULL)) s(id,a,b)', NULL,0)
-- working workaround
SELECT name, system_type_name
FROM sys.dm_exec_describe_first_result_set('
SELECT *
FROM (VALUES(1, cast(NULL as int), 100),
(2, NULL, NULL)) s(id,a,b)', NULL,0)
For all cases all columns are INT but with explicit CAST it behaves as it should.
db<>fidde metadata
This has nothing to do with the number of rows. It is because the values in one of the columns of the 2-row version are always NULL. The default type of NULL is int and the default type of a numeric constant (of this length) is int, so these should be comparable. But from a values() derived table, these are (apparently) not exactly the same type.
In particular, a column with only typeless NULLs from a derived table is not comparable, so it is excluded from the binary checksum calculation. This does not occur in a real table, because all columns have types.
The rest of the answer illustrates what is happening.
The code behaves as expected with type conversions:
SELECT *, BINARY_CHECKSUM(a, b) AS bc
FROM (VALUES(1, cast(NULL as int), 100),
(2, NULL, NULL)
) s(id,a,b);
Here is a db<>fiddle.
Actually creating tables with the values suggests that columns with only NULL values have exactly the same type as columns with explicit numbers. That suggests that the original code should work. But an explicit cast also fixes the problem. Very strange.
This is really, really strange. Consider the following:
select v.*, checksum(a, b), checksum(c,b)
FROM (VALUES(1, NULL, 100, NULL),
(2, 1, 2, 1.0)
) v(id, a, b, c);
The change in type for "d" affects the binary_checksum() for the second row, but not for the first.
This is my conclusion. When all the values in a column are binary, then binary_checksum() is aware of this and the column is in the category of "noncomparable data type". The checksum is then based on the remaining columns.
You can validate this by seeing the error when you run:
select v.*, binary_checksum(a)
FROM (VALUES(1, NULL, 100, NULL),
(2, NULL, 2, 1.0)
) v( id,a, b, c);
It complains:
Argument data type NULL is invalid for argument 1 of checksum function.
Ironically, this is not a problem if you save the results into a table and use binary_checksum(). The issue appears to be some interaction with values() and data types -- but something that is not immediately obvious in the information_schema.columns table.
The happyish news is that the code should work on tables, even if it does not work on values() generated derived tables -- as this SQL Fiddle demonstrates.
I also learned that a column filled with NULLs really is typeless. The assignment of the int data type in a select into seems to happen when the table is being defined. The "typeless" type is converted to an int.
For the literal NULL without the CAST (and without any typed values in the column) it entirely ignores it and just gives you the same result as BINARY_CHECKSUM(b).
This seems to happen very early on. The initial tree representation output from
SELECT *, BINARY_CHECKSUM(a,b) AS bc
FROM (VALUES(1, NULL, 100),
(2, NULL, NULL)) s(id,a,b)
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);
Already shows that it has decided to just use one column as input to the function
ScaOp_Intrinsic binary_checksum
ScaOp_Identifier COL: Union1008
This compares with the following output for your first query
ScaOp_Intrinsic binary_checksum
ScaOp_Identifier COL: Union1011
ScaOp_Identifier COL: Union1010
If you try and get the BINARY_CHECKSUM with
SELECT *, BINARY_CHECKSUM(a) AS bc
FROM (VALUES(1, NULL, 100)) s(id,a,b)
It gives the error
Msg 8184, Level 16, State 1, Line 8 Error in binarychecksum. There are
no comparable columns in the binarychecksum input.
This is not the only place where an untyped NULL constant is treated differently from an explicitly typed one.
Another case is
SELECT COALESCE(CAST(NULL AS INT),CAST(NULL AS INT))
vs
SELECT COALESCE(NULL,NULL)
I'd err on the side of "glitch" in this case rather than "by design" though as the columns from the derived table are supposed to be int before they get to the checksum function.
SELECT COALESCE(a,b)
FROM (VALUES(NULL, NULL)) s(a,b)
Does work as expected without this glitch.
I have 2 tables :
table1 t_SearchCriteria:
------------------------------
ID | VALUE | IDParent |
-----|------------|------------|
0 | root | -1 |
-----|------------|------------|
1 | JAMES | 0 |
-----|------------|------------|
2 | ISAC | 0 |
-----|------------|------------|
3 | LISA | 1 |
-----|------------|------------|
4 | Andrew | 3 |
-----|------------|------------|
5 | LISA | 2 |
-----|------------|------------|
6 | EZREAL | 5 |
-----|------------|------------|
10 | twitch | 2 |
-----|------------|------------|
13 | LUX | 0 |
-----|------------|------------|
14 | LISA | 13 |
-----|------------|------------|
15 | EZREAL | 14 |
-----|------------|------------|
EDIT: here is a representation of the tree:
_______root_______
/ | \
JAMES ISAC LUX
| / \ |
LISA TWITCH LISA LISA
| | |
Andrew EZREAL EZREAL
and my second table is like the following :
table t_Path
idPath|Person1| Son |grandSon|grandgrandSon|
------|-------|-------|--------|-------------|
1 |root |JAMES | LISA |ANDREW |
------|-------|-------|--------|-------------|
2 |root |ISAC | LISA |EZREAL |
------|-------|-------|--------|-------------|
3 |root |ISAC | NULL |TWITCH |
------|-------|-------|--------|-------------|
4 |root |LUX | NULL | NULL |
------|-------|-------|--------|-------------|
5 |root |LUX | LISA | NULL |
------|-------|-------|--------|-------------|
6 |root |LUX | LISA | EZREAL |
------|-------|-------|--------|-------------|
My need is to figure out a way (function or procedure) that starts from table 2 (t_Path) and find each leaf (value of grandgrandSon if not null otherwise grandson if not null etc...) id in t_searchCriteria table:
Since we can have the same value of node in the t_search criteria table then the unicity of a node is its value and its parent value and its grandParentValue (and we have another rule; a parent can't have 2 childs with same name)
I have tried to make a function but i didn't find a way to do a function inside another function besides working with objects like in c# or another programming laguage.
I need to make a function that takes an int ID wich is the ID of a path from table t_Path and figure out the leaf of the path (this is done), the problem here is how to get the id of that leaf from t_searchCriteria table since we can have multiple criterias with same value (name) even with same parent name, the grandParent Value will make difference.
for example of execution:
Select FunctionGetCriteriaId(6)
will return 15
where 6 is the id of the path : 6 |root |LUX | LISA | EZREAL |
and 15 is the id of the criteria : 15 | EZREAL | 14 |
Can anyone help me to figure this out please?
EDIT: to be more specific the fucntion takes the id of the path in table 2, for example 5 ( 5 |root |LUX | LISA | NULL |) and returns the id of "LISA" (the leaf not the others ;) ) in table 1 that is 14. (ofcourse taking note of the rules set before.)
EDIT 2:
updated unicity condition in the tree
You can do this easily using LEFT JOINS and MAX and COALESCE. This is full working example. You can play with it:
DECLARE #t_SearchCriteria TABLE
(
[ID] SMALLINT
,[Value] VARCHAR(12)
,[IDParent] SMALLINT
);
INSERT INTO #t_SearchCriteria ([ID], [Value], [IDParent])
VALUES (0, 'root', -1)
,(1, 'JAMES', 0)
,(2, 'ISAC', 0)
,(3, 'LISA', 1)
,(4, 'Andrew', 3)
,(5, 'LISA', 2)
,(6, 'EZREAL', 5)
,(10, 'twitch', 2)
,(13, 'LUX', 0)
,(14, 'LISA', 13)
,(15, 'EZREAL', 14);
DECLARE #t_Path TABLE
(
[idPath] SMALLINT
,[Person1] VARCHAR(12)
,[Son] VARCHAR(12)
,[grandSon] VARCHAR(12)
,[grandgrandSon] VARCHAR(12)
);
INSERT INTO #t_Path ([idPath], [Person1], [Son], [grandSon], [grandgrandSon])
VALUES (1, 'root', 'JAMES', 'LISA', 'ANDREW')
,(2, 'root', 'ISAC', 'LISA', 'EZREAL')
,(3, 'root', 'ISAC', 'TWITCH', NULL)
,(4, 'root', 'LUX', NULL, NULL)
,(5, 'root', 'LUX', 'LISA', NULL)
,(6, 'root', 'LUX', 'LISA', 'EZREAL');
-- the function input parameter
DECLARE #idPath SMALLINT = 5;
-- the function body
DECLARE #Person1 VARCHAR(12)
,#Son VARCHAR(12)
,#grandSon VARCHAR(12)
,#grandgrandSon VARCHAR(12);
SELECT #Person1 = [Person1]
,#Son = [Son]
,#grandSon = [grandSon]
,#grandgrandSon = [grandgrandSon]
FROM #t_Path P
WHERE P.[idPath] = #idPath;
SELECT COALESCE(MAX(S5.[ID]), MAX(S4.[ID]), MAX(S3.[ID]), MAX(S2.[ID]), MAX(S1.[ID]))
FROM #t_SearchCriteria S1
LEFT JOIN #t_SearchCriteria S2
ON S1.[ID] = S2.[IDParent]
AND S1.[Value] = #Person1
LEFT JOIN #t_SearchCriteria S3
ON S2.[ID] = S3.[IDParent]
AND S2.[Value] = #Son
AND #Person1 IS NOT NULL
LEFT JOIN #t_SearchCriteria S4
ON S3.[ID] = S4.[IDParent]
AND S3.[Value] = #grandSon
AND #grandgrandSon IS NOT NULL
LEFT JOIN #t_SearchCriteria S5
ON S4.[ID] = S5.[IDParent]
AND S4.[Value] = #grandgrandSon
WHERE S1.[Value] = #Person1;
I have two separate tables, each containing character-separated cells. One table contains all the key data, the other all the val data. In the application, both tables are loaded into recordsets, the two cells are split into two arrays and the arrays are then used 'side-by side' to create key/val pair.
Trying to decouple the database from the application, I will basically create a view that emulates this behavior.
I created some sample tables and data to better illustrate it.
/* Create tables */
CREATE TABLE [dbo].[tblKeys](
[KeyId] [int] NOT NULL, /*PK*/
[KeyData] [nvarchar](max) NULL
)
CREATE TABLE [dbo].[tblValues](
[ValId] [int] NOT NULL, /*PK*/
[KeyId] [int] NOT NULL, /*FK*/
[Language] [nvarchar](5) NOT NULL,
[ValData] [nvarchar](max) NULL
)
/* Populate tables */
INSERT INTO [dbo].[tblKeys] ([KeyId], [KeyData]) VALUES
(1, '1|2|3'),
(2, '1|2|3|4'),
(3, '2|1')
INSERT INTO [dbo].[tblValues] ([ValId], [KeyId], [Language], [ValData]) VALUES
(1, 1, 'en', 'Apple|Orange|Pear'),
(2, 1, 'sv-se', 'Äpple|Apelsin|Päron'),
(3, 2, 'en', 'Milk|Butter|Cheese|Cream'),
(4, 2, 'sv-se', 'Mjölk|Smör|Ost|Grädde'),
(5, 3, 'en', 'Male|Female'),
(6, 3, 'sv-se', 'Man|Kvinna')
The desired end result in the view looks like this:
| KeyId | KeyData | Language | ValData
+-------+---------+----------+----------+
| 1 | 1 | en | Apple |
| 1 | 2 | en | Orange |
| 1 | 3 | en | Pear |
| 1 | 1 | sv-se | Äpple |
| 1 | 2 | sv-se | Apelsin |
| 1 | 3 | sv-se | Päron |
...
etc.
I've seen similar questions here on StackOverflow, but they all deal with a single table being tilted in similar ways. I need to tilt both tables while using the positions of the data in the two columns KeyData and ValData as siginficants when recombining them into proper key/val pairs.
How would I do this in an efficient manner?
[Edit]: The database design is not mine. It's some old crap I inhereted. I know it's bad. Bad as in horrendous.
This would work for you. But: you really should change your data design!
;WITH Splitted AS
(
SELECT v.Language
,v.ValData
,v.ValId
,k.KeyData
,k.KeyId
,CAST('<x>' + REPLACE(v.ValData,'|','</x><x>') + '</x>' AS XML) AS ValData_XML
,CAST('<x>' + REPLACE(k.KeyData,'|','</x><x>') + '</x>' AS XML) AS KeyData_XML
FROM tblValues AS v
INNER JOIN tblKeys AS k ON v.KeyId=k.KeyId
)
,NumberedValData AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY KeyId,Language ORDER BY (SELECT NULL)) AS RowNumber
,KeyId
,Language
,A.B.value('.','varchar(max)') AS ValD
FROM Splitted
CROSS APPLY Splitted.ValData_XML.nodes('/x') AS A(B)
)
,NumberedKeyData AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY KeyId,Language ORDER BY (SELECT NULL)) AS RowNumber
,KeyId
,Language
,A.B.value('.','varchar(max)') AS KeyD
FROM Splitted
CROSS APPLY Splitted.KeyData_XML.nodes('/x') AS A(B)
)
,Combined AS
(
SELECT nk.KeyId
,nk.KeyD
,nk.Language
,nv.ValD
FROM NumberedKeyData AS nk
INNER JOIN NumberedValData AS nv ON nk.KeyId=nv.KeyId AND nk.Language=nv.Language AND nk.RowNumber=nv.RowNumber
)
SELECT Combined.KeyId
,Combined.KeyD AS KeyData
,Splitted.Language
,Combined.ValD AS ValData
FROM Splitted
INNER JOIN Combined ON Splitted.KeyId=Combined.KeyId AND Splitted.Language=Combined.Language
ORDER BY Splitted.KeyId,Splitted.
The result
KeyId KeyData Language ValData
1 1 en Apple
1 2 en Orange
1 3 en Pear
1 1 sv-se Äpple
1 2 sv-se Apelsin
1 3 sv-se Päron
2 1 en Milk
2 2 en Butter
[...]
I'm writing recursive sql against a table that contains circular references.
No problem! I read that you can build a unique path to prevent infinite loops. Now I need to filter the list down to only the last record in the chain. I must be doing something wrong though. -edit I'm adding more records to this sample to make it more clear why just selecting the longest record doesn't work.
This is an example table:
create table strings (id int, string varchar(200));
insert into strings values (1, '1');
insert into strings values (2, '1,2');
insert into strings values (3, '1,2,3');
insert into strings values (4, '1,2,3,4');
insert into strings values (5, '5');
And my query:
select * from strings str1 where not exists
(
select * from strings str2
where str2.id <> str1.id
and str1.string || '%' like str2.string
)
I'd expect to only get the last records
| id | string |
|----|---------|
| 4 | 1,2,3,4 |
| 5 | 5 |
Instead I get them all
| id | string |
|----|---------|
| 1 | 1 |
| 2 | 1,2 |
| 3 | 1,2,3 |
| 4 | 1,2,3,4 |
| 5 | 5 |
Link to sql fiddle: http://sqlfiddle.com/#!15/7a974/1
My problem was all around the 'LIKE' comparison.
select * from strings str1
where not exists
(
select
*
from
strings str2
where
str2.id <> str1.id
and str2.string like str1.string || '%'
)