2013-02-06 25 views
0

我有一個系統,允許用戶將特定文件分配到過去或當前日期。限制是他們只能每個用戶每天上傳一個文件。當用戶上傳文件時,日期字段必須默認爲當前日期,當該日期不可用時,它將以DESC順序顯示過去的第一個可用日期。以下是相關的字段名稱。從數據庫中獲取下一個可用日期

file_id (INT - INDEX - AUTO INCREMENT) 
user_id (INT - may index this) 
upload_date (INT - stores date as a unix timestamp) 

唯一的解決辦法,我真的發現將他們全部建成日期和環路DESC順序陣列通過,直到我發現了一個空槽。但是,我覺得如果用戶已經填滿了過去的一千天,這可能會導致速度問題。我覺得我忽略了一個簡單的解決方案。

請注意:出於某種原因,他們日期被存儲爲一個Unix時間戳,我明白的缺點,我不關心糾正在這個時候。

回答

1

爲了讓尚未使用最近的日期:

select user_id, max(date) - 1 
from (select ud.*, 
      (select max(date) from upload_date ud2 where ud2.user_id = ud.user_id and ud2.date < ud.date 
      ) as prevdate 
     from upload_date ud 
    ) ud 
where date(from_unixtime(ud.prevdate)) <> date(from_unixtime(ud.date)) - 1 or 
     ud.prevdate is null 
group by user_id 

該查詢首先獲得使用相關子查詢任意一天以前日期。然後它將時間值轉換爲日期並選擇前一日期有間隙的任何行。日期中最大的一個是你正在查找的日期。

該SQL未經測試,因此可能有語法錯誤。

+0

這是一個不錯的方法。當用戶在表中只有一行時會發生什麼。他今天已經上傳了一個文件,但之前沒有上傳過文件?此查詢是否會返回昨天的日期? – spencer7593

+0

@ spencer7593。 。 。通過我的快速編輯,日期將被選中(我在'where'子句中檢查了NULL)。 –

+0

謝謝!這也是一個非常快速的查詢。 – Patcouch22

1

解決此問題的一種方法是使用經典的「返回缺少的行」查詢。基本上,爲了獲得從數據庫返回的「缺失」行,您需要一種方法來生成「缺少」行。

SELECT MAX(t.upload_date) 
    FROM mytable t 
WHERE t.upload_date <= NOW() 
    AND t.user = 'someuser' 

獲得初始日期,我們打算從逆向操作:

要建立這樣的查詢,我們可以開始。

對於「每日一次」要求,您可能希望截斷該upload_date到午夜,至少對於此查詢。現在,我們假定SELECT列表中的表達式已被截斷,以說明方法,而不會陷入處理unix時間戳的細節。

要生成日期的降序列表,從先前查詢檢索到的初始日期...

SELECT s.upload_date - INTERVAL n.d DAY AS available_date 
    FROM (SELECT MAX(t.upload_date) AS upload_date 
      FROM mytable t 
      WHERE t.upload_date <= NOW() 
      AND t.user = 'someuser' 
     ) s 
CROSS 
    JOIN (SELECT 0 AS d UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 
     UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 
     UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 
     ) n 
ORDER BY n.d DESC 

有了這個結果,我們可以使用反連接模式來查找這些日期都沒有已使用。這是一個LEFT JOIN和拋出一個謂詞匹配的行:

SELECT s.upload_date - INTERVAL n.d DAY AS available_date 
    FROM (SELECT MAX(t.upload_date) AS upload_date 
      FROM mytable t 
      WHERE t.upload_date <= NOW() 
      AND t.user = 'someuser' 
     ) s 
CROSS 
    JOIN (SELECT 0 AS d UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 
     UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 
     UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 
     ) n 
    LEFT 
    JOIN mytable u 
    ON u.upload_date = s.upload_date - INTERVAL n.d DAY 
    AND u.user = 'someuser' 
WHERE u.upload_date IS NULL 
ORDER BY n.d DESC 
LIMIT 1 

這隻會回溯9天,讓它回頭多天,只是延長別名正線視圖返回更多的連續整數。 (我們可以使用一些技巧來交叉連接以獲取整數整數。)

剩下的就是工作的 「匹配」 的標準(這與MySQL DATE數據類型的作品):

ON u.upload_date = s.upload_date - INTERVAL n.d DAY 

弄成這個樣子:

ON u.upload_date >= UNIX_TIMESTAMP(FROM_UNIXTIME(s.upload_date)-INTERVAL n.d+1 DAY) 
    AND u.upload_date < UNIX_TIMESTAMP(FROM_UNIXTIME(s.upload_date)-INTERVAL n.d DAY) 

並與整數把玩時間戳值來獲取MySQL DATE ...

SELECT DATE(FROM_UNIXTIME(s.upload_date)) - INTERVAL n.d DAY AS available_date 
相關問題