これにアプローチする1つの方法は、従来の「欠落している行を返す」クエリを使用することです。基本的に、データベースから返される「欠落している」行を取得するには、「欠落している」行を生成する方法が必要です。
このようなクエリを作成するには、次のように開始できます。
SELECT MAX(t.upload_date)
FROM mytable t
WHERE t.upload_date <= NOW()
AND t.user = 'someuser'
これにより、最初の日付が取得されます。これから逆方向に作業します。
「1日1回」の要件の場合、少なくともこのクエリでは、upload_dateを深夜に切り捨てる必要があります。今のところ、UNIXタイムスタンプの処理の詳細にとらわれることなく、アプローチを説明するために、SELECTリストの式はすでに切り捨てられていると想定します。
前のクエリで取得した最初の日付から開始して、日付の降順リストを生成するには...
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
その結果、結合防止パターンを使用して、まだ使用されていない日付を見つけることができます。これはLEFTJOINであり、一致する行をスローする述語です。
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日だけを振り返ります。さらに日を振り返るには、nとしてエイリアスされたインラインビューを拡張して、より多くの連続する整数を返します。(整数のボートロード全体を取得するためにクロス結合で遊ぶことができるいくつかのトリックがあります。)
残っているのは、「一致する」基準(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)
そして、整数のタイムスタンプ値をいじって、MySQLDATEを取得します...
SELECT DATE(FROM_UNIXTIME(s.upload_date)) - INTERVAL n.d DAY AS available_date