2011-09-16 124 views
0

我有一個查詢寫,這有點太複雜,我想弄明白。幫助將不勝感激。 我的表,在本質:半複雜學說查詢

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 ==「你好」,IF組中的所有記錄都有一個時間戳<所有記錄=當前時間組中的一條記錄的時間戳< =當前時間 - 30分鐘。

希望這是有道理的。如果沒有,請告訴我,我會盡力澄清。

編輯:我希望有剛剛欄會爲一個例子就足夠了,但在現實中我的實際表中有多個列必須相匹配,以指示記錄是相關的。我已經相應地更新了示例。

+0

我不知道你的數據,但它看起來像{bar1,bar2,bar3}組成一個組,它可以被「標準化」到一個單獨的表中。 – wildplasser

回答

1

如果我理解你的問題correcty,你WANT爲(BAR1,BAR2,BAR3)=所有記錄(100,5, '你好')和你HAVE一定current_time作爲唯一一個輸入標準。

作爲第一步,我重申了兩個條件:爲了檢索組的成員,組的最大時間戳必須在過去(您的第一個條件)或組的最小時間戳必須至少30分鐘(相當於你的第二個條件)。

這樣你就可以查看該組及其與此查詢時間戳:

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

添加過濾器:(注意psql特殊語法\set: - 這是僅用於測試)

\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 

這將不返回任何current_time = 2011-01-01 00:31:00,因爲沒有組完成,沒有未完成的組ID足夠長。之後,由於子句而返回(100,5,Hello)組,並且在進一步增加current_time的同時返回另一個組。

到目前爲止好 - 最後一塊是檢索所有發現的組的成員:

SELECT * FROM foo WHERE (bar1, bar2, bar3) in (
     SELECT bar1, bar2, bar3 FROM foo 
     -- add WHERE clause with constraints based on bar1, bar2, bar3 here 
     GROUP BY bar1, bar2, bar3 
     HAVING max(timestamp) <= :current_time OR min(timestamp) +'30min' <= :current_time 
    ) 
    -- add further constraints here 

如果我對您輸入paramters第一個假設是錯誤的,你當然可以添加過濾器,每一種適宜的步驟的查詢。在前面的步驟中進行過濾當然會更有效率。我添加了合適的標記註釋。

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」使用子選項來獲取任何條形碼號碼,其中至少有一條記錄的時間戳低於或等於當前時間 - 30分鐘。

「bar =」只是將其限制爲特定的小節編號。

+0

如果bar實際上是bar1,bar2,bar3,你會如何調整? – clang1234