Reputation: 7855
SELECT searches.id, searches.tags, STRING_AGG(tags.name,',') tag_list
FROM searches
INNER JOIN notes ON notes.id = searches.note_id
INNER JOIN tags ON tags.note_id = notes.id
WHERE searches.tags <> 'tags_list'
GROUP BY searches.id
LIMIT 1;
I'm getting this result
id | tags | tag_list
-------+----------------------+----------------------
40283 | abcde,hello,sed,test | abcde,hello,sed,test
I've specified to return only cases where searches.tags <> 'tags_list'
but am seeing the opposite result.
SELECT id, tags, note_id FROM searches WHERE searches.note_id = 3;
id | tags | note_id
-------+-----------------------------+---------
40285 | at,asperiores,incidunt,unde | 3
(1 row)
SELECT id, name, note_id FROM tags WHERE tags.note_id = 3;
id | name | note_id
----+------------+---------
6 | at | 3
7 | asperiores | 3
8 | incidunt | 3
9 | unde | 3
(4 rows)
I would expect my query does not return search 40285 when I use a <>
operator. Conversely it would return it if I used a =
operator.
Upvotes: 0
Views: 69
Reputation:
You need to use the having
clause to filter on the result of an aggregation. But you can't use the column alias in the HAVING clause, you need to repeat the expression.
However, the comparison between the aggregated tag names and the stored tag names is unreliable because the order in the aggregation result is undefined. If you always store the tag names sorted alphabetically in searches.tags
then you should sort the names in the aggregation as well.
Note that, if searches.id
is not a primary or unique key in the table searches
, then you would also need to include searches.tags
in the group by
.
SELECT searches.id, searches.tags, STRING_AGG(tags.name,',' order by tags.name) tag_list
FROM searches
JOIN notes ON notes.id = searches.note_id
JOIN tags ON tags.note_id = notes.id
GROUP BY searches.id
HAVING searches.tags <> STRING_AGG(tags.name,',' order by tags.name)
LIMIT 1
If you don't want to repeat the expression, use a derived table:
select *
from (
SELECT searches.id, searches.tags, STRING_AGG(tags.name,',' order by tags.name) tag_list
FROM searches
JOIN notes ON notes.id = searches.note_id
JOIN tags ON tags.note_id = notes.id
GROUP BY searches.id
) t
WHERE tags <> tag_list
LIMIT 1
Upvotes: 4
Reputation: 32003
add searches.tags
column in group by as you are using aggregation
SELECT searches.id, searches.tags, STRING_AGG(tags.name,',') tag_list
FROM searches
INNER JOIN notes ON notes.id = searches.note_id
INNER JOIN tags ON tags.note_id = notes.id
WHERE searches.tags <> 'tags_list'
GROUP BY searches.id,searches.tags
LIMIT 1;
Upvotes: 1