故事是這樣的...我有Users
,他們有Children
。 我想每天使用CRON JOB優惠券發送給有子女出生日期間隔的用戶。 我想知道誰將是用戶獲得優惠券和哪個孩子。 我也想爲每個孩子只發送一張優惠券,孩子必須是用戶擁有的最小的優惠券。GROUP BY和ORDER BY在聯合表 - 複雜和緩慢
我有以下表
Children
+--------------------------------------+
- Primary Key: childrenID (int)
- Index: userID (int)
- Index: childBirthDate (date)
+--------------------------------------+
- childrenID - userID - childBirthDate -
- 1 - 1 - 21/01/2000 -
- 2 - 1 - 01/11/2013 -
- 3 - 1 - 25/10/2013 -
- 4 - 2 - 01/11/2013 -
- 5 - 3 - 01/11/2013 -
+--------------------------------------+
Users
+------------------------+
- Primary Key: userID (int)
- Index: categoryGroup (varchar)
+------------------------+
- userID - categoryGroup -
- 1 - 'Group1' -
- 2 - 'Group1' -
- 3 - 'Group2' -
- 4 - 'Group2' -
+------------------------+
CuponRequests
+------------------------+
- Primary Key: ID (int)
- Index: userID (int)
- Index: cuponID (int)
+-----------------------+
- ID - cuponID - userID -
- 1 - 1 - 1 -
- 1 - 2 - 1 -
- 1 - 1 - 2 -
+-----------------------+
這基本上是與相關列 三個主要的表,我有以下SQL查詢來執行,並獲取我需要的結果。
SELECT users.userID,
users.categoryGroup children.childBirthDate,
children.childrenID
FROM users,
(SELECT *
FROM
(SELECT children.childrenID,
children.childBirthDate,
users.userID AS child_uid
FROM children,
users
WHERE children.userID = users.userID
ORDER BY children.childBirthDate DESC)t1
GROUP BY child_uid)children
WHERE (children.childBirthDate <= DATE_SUB(CURDATE(), INTERVAL 5 MONTH))
AND (children.childBirthDate > DATE_SUB(CURDATE() , INTERVAL 6 MONTH))
AND (children.child_uid = users.userID)
AND ('Group1, Group2' LIKE CONCAT('%', users.categoryGroup, '%'))
AND NOT EXISTS
(SELECT userID,
cuponID
FROM cuponRequests
WHERE userID = users.userID
AND cuponID = 1)
AND userID = 1
ORDER BY children.childBirthDate DESC
對於此查詢我想只有一個用戶,並只在一個優惠券 但它的工作是理所當然的行爲 - 查詢正在對所有的用戶
的「cuponID」,和間隔,來自腳本的PHP端 - 我迭代「cupons」表(這裏沒有提到),並在每個「優惠券」行上執行此查詢)
問題是此查詢正在執行1.5秒(OO) 除了在CRON JOB環境中運行此腳本外,此腳本也運行在用戶註冊到網站之後。我有96個cupons - 這使得減慢登記約1分鐘(這是一個很大)
我盤算了一下,這個查詢
SELECT *
FROM
(SELECT children.childrenID,
children.childBirthDate,
users.userID AS child_uid
FROM children,
users
WHERE children.userID = users.userID
ORDER BY children.childBirthDate DESC)t1
GROUP BY child_uid
會減慢速度。我試圖做的,而不是一個JOIN關選擇查詢這樣的選擇查詢裏面:
FROM users LEFT JOIN children ON children.userID = users.userID
但後來我失去了「ORDER BY childBirthDate DESC」來獲得該用戶的最小的孩子,我失去了「GROUP BY child_uid「只得到他的一個孩子
任何想法如何使事情更快,但仍然工作?
P.S 對不起,我缺乏英語。
編輯:
這裏是輸出EXPLAIN SQL
+----+--------------------+---------------+-------+----------------+---------+---------+------------------------------+-------+-----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+---------------+-------+----------------+---------+---------+------------------------------+-------+-----------------------------------------------------+
| 1 | PRIMARY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE noticed after reading const tables |
| 4 | DEPENDENT SUBQUERY | cuponRequests | ref | userID,cuponID | userID | 5 | const | 1 | Using where |
| 2 | DERIVED | <derived3> | ALL | NULL | NULL | NULL | NULL | 73526 | Using temporary; Using filesort |
| 3 | DERIVED | users | index | PRIMARY | PRIMARY | 4 | NULL | 69271 | Using index; Using temporary; Using filesort |
| 3 | DERIVED | children | ref | userID | userID | 4 | users.userID | 1 | |
+----+--------------------+---------------+-------+----------------+---------+---------+------------------------------+-------+-----------------------------------------------------+
什麼是您的INDEX?如果有的話 – nrathaus
您的日期是否使用DATE數據類型存儲?另外,「我想只爲每個孩子發送一個cupon,並且孩子必須是用戶擁有的最老的。」 - 最古老的可讀孩子,還是最古老的孩子,完全停下來? – Strawberry
爲問題添加了索引 –