Прежде всего, массивы нужны для идентификаторов обеих сторон оператора &&
, например STRING_TO_ARRAY(translate(tags::text, '[] "', ''), ',')::text[]
вместо tags
и STRING_TO_ARRAY('foo,bar,baz',','))
вместо '{"foo", "bar", "baz"}'
шаблона соответственно.
Затем вы можете разложить элементы массива для столбца тегов, используя функцию JSON_ARRAY_ELEMENTS()
, чтобы подсчитать появление каждого элемента возвращаемых value
столбцов в шаблоне '{"foo", "bar", "baz"}'
с помощью функций STRPOS()
и SIGN()
вместе с агрегированием SUM()
:
SELECT name, tags::text
FROM "nodes"
CROSS JOIN JSON_ARRAY_ELEMENTS(tags) AS js
WHERE ( STRING_TO_ARRAY(translate(tags::text, '[] "', ''), ',')::text[]
&& STRING_TO_ARRAY('foo,bar,baz',','))
GROUP BY name, tags::text
ORDER BY SUM( SIGN( STRPOS('{"foo", "bar", "baz"}'::text,value::text) ) ) DESC
Но у вас могут быть повторяющиеся элементы в столбце tags
. В этом случае вышеуказанный запрос не выполняется. Итак, я предлагаю использовать этот ниже, содержащий строки, исключенные ключевым словом DISTINCT
:
SELECT name, tags
FROM
(
SELECT DISTINCT name, tags::text, STRPOS('{"foo", "bar", "baz"}'::text,value::text)
FROM "nodes"
CROSS JOIN JSON_ARRAY_ELEMENTS(tags) AS js
WHERE ( STRING_TO_ARRAY(translate(tags::text, '[] "', ''), ',')::text[]
&& STRING_TO_ARRAY('foo,bar,baz',','))
) n
GROUP BY name, tags::text
ORDER BY SUM( SIGN( strpos ) ) DESC
Demo