Я использую SQLite и хочу получать только строки со значениями, уникальными для каждой таблицы. Я знаю, как получить значения для каждого столбца, но не могу создать один (совместимый с sqlite) выбор, чтобы получить уникальное значение из обоих столбцов.
Вот пример данных:
Моим желаемым результатом из приведенного выше примера были бы строки с уникальными значениями, которые включают только: 444, 555, 666.
222 не должно быть в результатах, так как оно появляется несколько раз в столбце col_A. 777 не должно быть в результатах, так как оно появляется несколько раз в col_B. Мне нужно только одно вхождение значения либо в col_A, либо в col_B. Уникальное значение для таблицы, а не для столбца.
Как далеко мне удалось зайти:
SELECT *
FROM my_table
WHERE
(SELECT col_A as asset from my_table GROUP BY col_A HAVING COUNT(*) = 1
UNION
SELECT col_B as asset from my_table GROUP BY col_B HAVING COUNT(*) = 1)
IN (col_A, col_B)
Я пробовал использовать UNION и несколько других подходов, но не смог добиться желаемого результата.
Вы написали 222 should not be in results as it appears multiple times in col_A, и все же это входит в ваши результаты.
@MatBailie, да, 222 присутствует в моем примере как одно из значений из-за выбора полной строки. Ваш ответ лучший, так как он заметно быстрее других. Я выделил жирным шрифтом значения в примере результата, так как они важны и результат зависит от них. Значения, не выделенные жирным шрифтом, в примерах результатов появляются только из-за полного выбора строки.


Я думаю, вам нужен такой запрос:
;with unqs as (
select col_c
from (
select col_c, count(col_c) cnt
from (
select col_A as col_c
from my_table
union all
select col_B as col_c
from my_table) as t
group by col_c) as tt
where cnt = 1
)
select *
from my_table
where col_A in (select col_c from unqs)
or col_B in (select col_c from unqs);
Чтобы начать фильтрацию с помощью UNION ALL, учитывая ключевое слово, либо
будет подходящим вариантом вместе с предложением HAVING для определения различных значений, таких как
WITH t1 AS
(
SELECT col
FROM (SELECT col_A AS col FROM t UNION ALL
SELECT col_B FROM t) AS tt
GROUP BY col
HAVING COUNT(*)=1
)
SELECT t.*
FROM t1
JOIN t
ON col IN ( col_A , col_B )
В зависимости от размера таблицы последний предикат соединения может быть довольно медленным (требуется сканирование). Возможно, будет лучше ОБЪЕДИНИТЬ два запроса, одно соединение в столбце A, другое соединение в столбце B, так как тогда индексы могут использоваться для поиска, если каждый столбец индексируется независимо.
Хотел пометить этот ответ как принятый, пока не появится лучший. Как упоминалось в комментарии выше, ваше решение работает медленнее при большем количестве строк. Первый запуск занимает 700-800 мс на 2000 строк. Решение Мата делает это за 150 мс.
WITH
symetric AS
(
SELECT col_a, col_b, col_a AS lookup FROM t
UNION ALL
SELECT col_a, col_b, col_b AS lookup FROM t
)
SELECT
col_a, col_b
FROM
symetric AS t
WHERE
NOT EXISTS (
SELECT *
FROM symetric
WHERE lookup = t.lookup
AND (col_a, col_b) <> (t.col_a, t.col_b)
)
ORDER BY
col_a, col_b
Демо ; https://dbfiddle.uk/9tzUASle
Спасибо. В настоящее время это самое быстрое решение моей проблемы. Как упоминалось в моем сообщении (OP), мне нужны все/несколько столбцов в реальном решении при возврате результата. Поэтому я изменил ваше решение, чтобы получить полный выбор строки из всех 10+ атрибутов.
@AndroidTank Для достижения наилучших результатов вам будет полезен столбец id и убедитесь, что у вас есть индексы на (col_a, id) (col_b, id), ..., (col_j, id), как выделено в демонстрации.
А как насчет стоимости
111? Он уникален в обоих столбцах. Что, если столбцы имеют разное количество уникальных значений?