我有一张这样的表:
id | value1 | value2 | value3
-----+--------+--------+--------
id1 | a | a | b
id2 | a | b | c
id3 | b | b | c
id4 | c | c | c
我想找到大多数值匹配的行(即至少有两个值匹配),因此对于上面给出的数据,输出I' d像:
id | majority_value
-----+----------------
id1 | a
id3 | b
id4 | c
答案 0 :(得分:3)
所有值列的日期类型必须匹配(或将所有值转换为相同类型)。
对于正好3列值的简单情况,这应该是最快的,所有这些 NOT NULL
。 id
列不必是唯一的。
SELECT id, CASE value1 WHEN value2 THEN value2 ELSE value3 END AS val
FROM tbl
WHERE value1 = value2 OR value2 = value3 OR value1 = value3
ORDER BY 1;
对NULL值不起作用。 (可以很容易地扩展。)
对于任意奇数个值列(为偶数定义一个决胜局!)。
id
列必须是唯一的。
SELECT t.id, t1.val
FROM tbl t
, LATERAL (VALUES (value1), (value2), (value3)) t1(val) -- list all
GROUP BY 1, 2
HAVING count(*) > 1 -- 1 being 3/2 (integer division)
ORDER BY 1;
SQL Fiddle(使用NULL值扩展的测试用例)。
甚至适用于NULL值。
答案 1 :(得分:1)
您可以尝试这种替代方案,看看它与您的解决方案的比较:
SELECT id, t.x
FROM value_table
JOIN LATERAL (
SELECT value1 AS x UNION ALL
SELECT value2 UNION ALL
SELECT value3) t ON true
GROUP BY id, t.x
HAVING COUNT(*) > 1
答案 2 :(得分:0)
这是一个可行的解决方案,它将不同的值组合到一个数组中,然后取消它们并计算出每个id的计数。这是查询:
SELECT id, value AS majority_value FROM (
SELECT id, unnest(values) AS value, count(1) FROM (
select *, array[value1, value2, value3] AS values from value_table
) a GROUP BY id, value
) b WHERE count > 1;
这是它的EXPLAIN ANALYZE输出:
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------
Sort (cost=2509.60..2559.60 rows=20000 width=64) (actual time=0.079..0.082 rows=3 loops=1)
Sort Key: b.id
Sort Method: quicksort Memory: 25kB
-> Subquery Scan on b (cost=778.83..1080.83 rows=20000 width=64) (actual time=0.058..0.067 rows=3 loops=1)
-> HashAggregate (cost=778.83..880.83 rows=20000 width=128) (actual time=0.056..0.059 rows=3 loops=1)
Filter: (count(1) > 1)
Rows Removed by Filter: 5
-> Seq Scan on value_table (cost=0.00..268.83 rows=51000 width=128) (actual time=0.014..0.032 rows=12 loops=1)
Total runtime: 0.127 ms
(9 rows)
我希望存在更有效的查询。