半复杂的学说查询

时间:2011-09-16 21:41:34

标签: php sql postgresql doctrine-orm

我有一个查询,我觉得这有点太复杂了。帮助将不胜感激。 我的表基本上是:

Table: Foo
Columns: id
         timestamp
         bar1
         bar2
         bar3

Bar1,bar2和bar3对于每条记录都不是唯一的。实际上,3的组合具体涉及多个记录。例如:

0 | 2011-01-01 00:01:01 | 100 | 5 | 'Hello'
1 | 2011-01-01 12:12:00 | 100 | 5 | 'Hello'
2 | 2011-01-01 07:43:00 | 101 | 8 | 'Monkey'
3 | 2011-01-01 17:46:08 | 102 | 9 | 'Cat'
4 | 2011-01-01 23:15:00 | 100 | 5 | 'Hello'
5 | 2011-01-01 10:00:00 | 100 | 6 | 'Goodbye'

记录0,1和4是相关的,而2,3和5是唯一的。

考虑到这一点,我想找到所有记录,其中bar1 == 100,bar2 == 5,bar3 =='Hello', IF 组中的所有记录都有时间戳&lt ; =当前时间 OR 组中的一条记录的时间戳<=到当前时间--30分钟。

希望这是有道理的。如果没有,请告诉我,我会尽力澄清。

编辑:我希望只有bar才足以作为一个例子,但实际上我的实际表有多个列必须匹配以指示记录是相关的。我相应地更新了这个例子。

2 个答案:

答案 0 :(得分:1)

如果我理解你的问题是正确的,你想要(bar1,bar2,bar3)的所有记录=(100,5,'你好')你拥有 a某些current_time是唯一的输入条件。

作为第一步,我重新描述了两个条件:为了检索组的成员,组的最大时间戳必须是过去的(您的第一个条件)或组的最小时间戳必须至少30分钟(相当于到你的第二个条件)。

因此,您可以使用此查询查看组及其时间戳:

    SELECT bar1, bar2, bar3, max(timestamp) group_end, min(timestamp) group_start 
        FROM foo 
        GROUP BY bar1, bar2, bar3;

添加过滤器:(请注意psql\set的{​​{1}}的特殊语法 - 仅供测试使用)

:

这将不会为 \set current_time '''2011-01-01 17:00:00''' SELECT bar1, bar2, bar3, max(timestamp) group_end, min(timestamp) group_start FROM foo GROUP BY bar1, bar2, bar3 HAVING max(timestamp) <= :current_time OR min(timestamp) +'30min' <= :current_time 返回任何内容,因为没有任何组已完成且没有未完成的组ID足够老。之后,由于 OR 子句而返回(100,5,Hello)组,并且在进一步增加current_time时返回另一组。

到目前为止一切顺利 - 最后一部分是检索所有找到的组的成员:

current_time = 2011-01-01 00:31:00

如果我对你的输入参数的第一个假设是错误的,你当然可以在查询的每个合适的步骤中添加过滤器。当然,在先前步骤中过滤将更具性能。我添加了合适的标记注释。

答案 1 :(得分:0)

我对postgresql不太熟悉,但这里是T-SQL的答案,应该返回你要查找的结果。我不认为它使用postgresql中不可用的任何命令,但我不确定。此外,它可能会在子选择中阻塞DISTINCT,如果是这样,只需删除它,因为它不是必需的。祝你好运。

SELECT *
FROM Foo
WHERE 
(
bar IN (SELECT bar 
        FROM (SELECT bar, MAX(timestamp) As HighestTime FROM Foo GROUP BY bar) HT 
        WHERE HT.HighestTime <= GETDATE())
OR bar IN (SELECT DISTINCT bar FROM Foo WHERE timestamp <= DATEADD(mm, -30, GETDATE())
) 
AND
bar = 100

第一个“bar in”使用子选择只获取那些所有时间戳都低于或等于当前日期时间的条形码,只需选中最大的一个。

第二个“bar in”使用子选项获取任何条形码,这些条形码至少有1条记录,时间戳小于或等于当前时间--30分钟。

“bar =”只是将其限制为特定的条形码。