Sql 查找(x,y)和(y,x)记录的最佳查询

Sql 查找(x,y)和(y,x)记录的最佳查询,sql,postgresql,Sql,Postgresql,假设我有一个表messages sender_id recipient_id ========== ============= 1 2 1 3 2 1 获取一个值为1,另一个值为2的记录的最佳查询是什么,即对于上面的示例数据集,它应该同时返回(1,2)和(2,1)。目前,我正在使用类似于: SELECT * FROM messages WHERE 1 IN (sender_id, recipient_id) AND 2

假设我有一个表
messages

sender_id    recipient_id
==========   =============
1            2
1            3
2            1
获取一个值为1,另一个值为2的记录的最佳查询是什么,即对于上面的示例数据集,它应该同时返回(1,2)和(2,1)。目前,我正在使用类似于:

SELECT *
FROM messages
WHERE 1 IN (sender_id, recipient_id) AND 2 IN (sender_id, recipient_id)
但这似乎是次优的。有更好的方法吗

编辑

  • 我不需要过滤掉重复的内容
  • 我有复合索引的发件人id和收件人id
如果需要,可以使用基于表达式的索引来支持:

create index from_to_index on messages 
  ( least(sender_id, recipient_id), greatest(sender_id, recipient_id) );
如果需要,可以使用基于表达式的索引来支持:

create index from_to_index on messages 
  ( least(sender_id, recipient_id), greatest(sender_id, recipient_id) );

如果发件人不能同时作为收件人:

select * from messages
where sender_id in (1, 2)
and recipient_id in (1, 2)
如果两者都有可能,请添加另一个筛选器:

select * from messages
where sender_id in (1, 2)
and recipient_id in (1, 2)
and sender_id != recipient_id

如果发件人不能同时作为收件人:

select * from messages
where sender_id in (1, 2)
and recipient_id in (1, 2)
如果两者都有可能,请添加另一个筛选器:

select * from messages
where sender_id in (1, 2)
and recipient_id in (1, 2)
and sender_id != recipient_id

在我看来,最直接的方法似乎是在中使用

select *
from messages
where (sender_id, recipient_id) in ((1, 2), (2, 1));

在SQLFiddle上的测试表明,它有时比Bohemian的答案快,有时慢,这取决于当前的数据。但对于可读性,我认为这更好。

在我看来,最直接的方法是在
中使用

select *
from messages
where (sender_id, recipient_id) in ((1, 2), (2, 1));

在SQLFiddle上的测试表明,它有时比Bohemian的答案快,有时慢,这取决于当前的数据。但对于可读性,我认为这更好。

这似乎是最快的,如果可用,它会使用索引,如果可能,它会使用延迟评估。@Victory:您的结论对基本索引有效(这是您在某些其他RDBMS中所能做的全部)。在Postgres中,查询与功能索引(如带有\u no\u名称的\u horse\u)结合使用会更快。只需一次索引扫描即可。@ErwinBrandstetter这将使用一次索引扫描,执行效果很好。除非对速度的需求非常关键,否则额外函数索引的麻烦和开销是浪费每个人的时间。无论如何,我怀疑速度差是否会明显。我认为简单的解决方案总是比复杂的更受欢迎。@Bohemian:不,不是。我在发布之前进行了测试,得到了两个位图索引扫描(带有两个单列索引)或一个位图索引扫描和一个位图堆扫描(带有一个多列索引),其中一个马的解决方案只需要一个索引扫描,速度大约是前者的两倍。出于同样的原因,我自己也在使用类似的解决方案。由于这两个查询都非常快,因此您的问题是正确的,除非您需要优化性能。Q请求
最佳查询
。因此我的评论。@ErwinBrandstetter好的,这是一个惊喜-我本来希望它只使用一个索引,并在另一个条件下过滤结果。关于“最优化”,这对不同的人来说可能意味着不同的东西。含义包括“最少的代码”、“最优雅”、“最可伸缩”、“最灵活”,当然还有“无论易读性或可维护性如何,都要从中挤出最后一点性能”“。这似乎是最快的,如果可用,它会使用索引,如果可能,它会使用惰性评估。@Victory:您的结论对基本索引有效(这就是您在某些其他RDBMS中所能做的全部)。在Postgres中,查询与功能索引(如带有\u no\u名称的\u horse\u)结合使用会更快。只需一次索引扫描即可。@ErwinBrandstetter这将使用一次索引扫描,执行效果很好。除非对速度的需求非常关键,否则额外函数索引的麻烦和开销是浪费每个人的时间。无论如何,我怀疑速度差是否会明显。我认为简单的解决方案总是比复杂的更受欢迎。@Bohemian:不,不是。我在发布之前进行了测试,得到了两个位图索引扫描(带有两个单列索引)或一个位图索引扫描和一个位图堆扫描(带有一个多列索引),其中一个马的解决方案只需要一个索引扫描,速度大约是前者的两倍。出于同样的原因,我自己也在使用类似的解决方案。由于这两个查询都非常快,因此您的问题是正确的,除非您需要优化性能。Q请求
最佳查询
。因此我的评论。@ErwinBrandstetter好的,这是一个惊喜-我本来希望它只使用一个索引,并在另一个条件下过滤结果。关于“最优化”,这对不同的人来说可能意味着不同的东西。含义包括“最少的代码”、“最优雅”、“最可伸缩”、“最灵活”,当然还有“无论易读性或可维护性如何,都要从中挤出最后一点性能”“。这应该是公认的答案。它比提出的备选方案(对于一些维持额外指数的间接成本)更快。这应该是公认的答案。它比提供的备选方案更快(对于维护额外索引的一些间接成本)。