2012-10-12 67 views
0

我們有一個系統,用戶向我們發送商品包裝袋。我該如何編寫這個MySQL查詢?

我想弄明白如何拉用戶與計算字段的日期,他們發送他們的第三袋商品。歷史表上表示此事件的狀態是「已處理」。如果我想只得到一個特定的包接收的日期我會寫:

SELECT bags.created_at FROM history 
WHERE history.state='received' AND history.bag_id LIMIT 1 

這裏是我們的表:

users 
    id 

bags 
    user_id 

history 
    state 
    bag_id 
    created_at 

的最終目標是一個選擇查詢,讓我們的用戶記錄,並增加了「字段」3rd_bag_received_at

任何想法?

+0

你在你的問題表明了'processed'事件將被存儲在'history.state'?而'history.bag_id'引用'bags.id'(你沒有在你的模式中列出)? – Sepster

+0

爲了實現這一目標,我專注於邏輯,我錯過了想要將其作爲計算列處理的一點,抱歉。我已經更新了我的答案,以反映如何管理該問題。 – Sepster

回答

3

你可以group by USER_ID,然後添加一個having條款只包括用戶count(distinct bag_id) >= 3

然後limit,爲3,和order by得到最新的日期max(created_at)

這是否幫助?

實施將是這個樣子:

select 
user.id, 
max(history.created_at) as third_bag_received_at 

from 
(

select 
    user.id, 
    max(history.created_at) 

from 
    users 

    inner join bags 
    on user.id = bags.user_id 

    inner join history 
    on bags.id = history.bag_id 

where history.state = 'processed' 

group by 
    user.id 

having 
    count(history.bag_id >= 3) 

limit 3 

order by 2 -- does this work in mySql? (It means "column 2" in MS SQL) 
) 

Limit 1 

編輯:如何應對加入/匯聚到其它表在計算列:

而不是增加這是一個計算列,我可能會創建一個視圖,其中包含您需要的任何信息,包括基於此查詢的third_bag_received列。

但是,如果你真的需要實現,這個是你的表計算列:

我建議創建一個接受你的user.id作爲輸入,並再次返回third_bag_received_at值(用戶功能,基於上述查詢的邏輯)。

然後從計算列中調用此函數。請參閱@ user10635的回答this SO question

0

我只是開發更多的Sepster答案來說清楚。 這個問題是不穩定的,因爲它沒有說餐桌袋有任何叫bag.id的字段,我必須補足。

SELECT users.id, MAX(history.created_at) as 3rd_bag_received_at 
FROM users LEFT JOIN bags ON (users.id=bags.user_id) 
LEFT JOIN history ON(bags.id = history.bag_id) 
WHERE history.state='received' 
GROUP BY users.id 
HAVING COUNT(history.bag_id) >= 3; 
+1

:-)我剛剛添加了一個具體的實現。幾個問題與這一個雖然 - '3rd_bag_recieved'不會是一個有效的名字,我想是因爲它以一個數字開頭。此外,你仍然不會限制第三包(例如,如果有四個或更多包),所以你實際上會得到_latest_包的日期,而不是第三包。而'history.state'需要被「處理」(我想!)。 – Sepster

+0

修復了Sepster指出的錯誤。 乾杯! SELECT users.id,SUBSTRING(CONCAT(history.created_at),19,29) 作爲third_bag_received_at FROM用戶LEFT JOIN袋ON(users.id = bags.user_id) LEFT JOIN歷史ON(bags.id = history.bag_id) WHERE history.state ='processed' GROUP BY users.id HAVING COUNT(history.bag_id)> = 3; –

+0

'SUBSTRING(CONCAT(history.created_at),19,29)'是新穎的。我的一部分人非常喜歡這個,因爲這是一種比我的第三種入門更簡單的方法。但不夠健壯;如果使用這種方法,特別是使用日期/時間,那麼您需要非常小心使用的日期格式,因爲這會與字符串位置緊密相關(也許某種注入分隔符模式可能更安全?)。但恕我直言,我不認爲我們應該求助於字符串操作_if_有一個基於集合的數據庫方法,將覆蓋它,性能(和純粹!)的原因。但它很聰明! :-) – Sepster