2012-11-02 96 views
1

我在我的數據庫表2:GROUP BY還選擇了非恆定列

log_visitors: 
-------------------- 
id | host_id 


log_access: 
-------------------- 
visitor | document | timestamp 

log_access.visitor鏈接log_visitors.id

目前,我使用此查詢:

SELECT 
    log_visitors.host_id 
    , MIM(log_access.timestamp) AS min_timestamp 
FROM 
    log_access 
    INNER JOIN log_visitors 
     ON (log_access.visitor = log_visitors.id) 
GROUP BY log_visitors.host_id; 

在數據庫中爲每個host_id獲得MIN(timestamp)

我的問題是:

我還需要得到document與該時間戳訪問......我不能簡單地添加到log_access.document SELECT列表,因爲它不是恆定的,我並沒有被文件分組。 .. 任何想法?

+1

行動查詢的其中一個例子是DBMS本作? –

回答

5

你沒有指定你的DBMS,但是這是ANSI SQL(在大多數現代DBMS工程)

select * 
from (
    SELECT log_visitors.host_id, 
     log_visitors.document, 
     log_access.timestamp 
     min(log_access.timestamp) OVER (partition by log_visitors.host_id) AS min_timestamp 
    FROM log_access 
    JOIN log_visitors ON (log_access.visitor = log_visitors.id) 
) t 
where t.timestamp = t.min_timestamp 
ORDER BY host_id 
+0

子查詢不需要「GROUP BY」嗎? –

+0

@ypercube:不,它不。這就是窗口功能的用途。 –

+0

啊,我錯過了外部的WHERE條件,對! –

3

類似下面的應該給你你想要的東西:

SELECT  lv.host_id, 
      mv.MinTime, 
      la.document 

FROM  log_visitors AS lv 
INNER JOIN  
      (SELECT visitor, 
        MIN(timestamp) AS MinTime 
      FROM log_access 
      GROUP BY visitor) AS mv ON lv.id = mv.visitor 
INNER JOIN log_access AS la ON lv.id = la.visitor AND mv.MinTime = la.timestamp 

我們所做的是獲取一個表中的所有訪問者列表和最小時間戳,加入到該列表中,然後重新加入時間戳上的日誌訪問以選擇特定文檔。

這使用ANSI SQL-92,因此應該適用於廣泛的數據庫系統,包括那些不支持窗口函數的系統。

這裏是通過Sql Fiddle

+0

謝謝,這真的有幫助!我的服務器是MySQL(OVER/PARTITION BY沒有工作)。現在我試圖弄清楚,如何獲取MAX(timestamp)和適當的文檔編號(所以我的結果表中有「MinTime,MaxTime,MinDocument,MaxDocument,id」等列)。它看起來也太 辛苦...... –

+0

@MichalKosek一個額外的連接聽起來是正確的,所以不要擔心它! – dash