我有这个查询,这对于更高版本的MySQL来说效果很好(我认为),但不幸的是,这不是一个选项。
我有一个彩票数据库,每个彩票都有用户的电子邮件地址。我需要找到这个彩票的赢家,但每个电子邮件地址只能有1张中奖彩票,即使他们有多张中奖彩票。我正在尝试使用多个子查询来完成此任务。
我只想将winner
='Y'设置为每封电子邮件的最高匹配数,因此用户每周只能获得1个“获胜者”。
我想为每封电子邮件更新1行,而不是整个表格中的1行。
我的目标是在单个查询中执行所有这些操作,或者至少尽可能减轻服务器上的压力。我每周要处理超过30,000行/票。
我认为最好的办法是使用JOIN而不是IN,但我无法弄明白。
UPDATE `tickets`
SET `winner`='Y'
WHERE `ticketid` IN
(SELECT `ticketid`
FROM `tickets`
WHERE `email` IN
(SELECT distinct(email)
FROM `tickets`
WHERE `date` BETWEEN '$weekstart' AND '$weekend'
AND `matches`>='3')
ORDER BY `matches` DESC LIMIT 1)
此查询给出了错误:“#1235 - 此版本的MySQL尚不支持'LIMIT& IN / ALL / ANY / SOME子查询'”
答案 0 :(得分:1)
除了 LIMIT & IN/ALL/ANY/SOME subquery
限制之外,在WHERE
语句的UPDATE
子句中,自行加入表是不可能的 - 没有一些技巧 - 甚至不是在最新的MySQL版本中。
使用连接重写通常更好 - 尽管远非琐碎:
UPDATE
( SELECT DISTINCT email
FROM tickets
) AS e
JOIN
tickets AS t
ON t.ticket_id =
( SELECT ti.ticket_id
FROM tickets AS ti
WHERE ti.email = e.email
AND ti.date BETWEEN '$weekstart' AND '$weekend'
AND ti.matches >= 3
ORDER BY ti.matches DESC
LIMIT 1
)
SET
t.winner = 'Y' ;
这只会为表格中的ticket_id
的每个不同值找到一个emails
(并且只有在添加条件的行中,所需周中的日期以及3个或更多&#34时;匹配")然后更新。
修改:我错了,上面的不工作,引发错误:
"#1093 - 您无法指定目标表' e'用于FROM子句中的更新"
但这(甚至更复杂)确实有效:
UPDATE
tickets AS u
JOIN
( SELECT t.ticket_id
FROM
( SELECT DISTINCT email
FROM tickets
) AS e
JOIN
tickets AS t
ON t.ticket_id =
( SELECT ti.ticket_id
FROM tickets AS ti
WHERE ti.email = e.email
AND ti.date BETWEEN '$weekstart' AND '$weekend'
AND ti.matches >= 3
ORDER BY ti.matches DESC
LIMIT 1
)
) AS x
ON x.ticket_id = u.ticket_id
SET
u.winner = 'Y' ;
关于效率,我认为(email, date, matches, ticket_id)
上的索引会改善它。
如果表中具有matches >= 3
的行的百分比很小,则替代索引将位于(email, matches, date, ticket_id)
上。
答案 1 :(得分:0)
您希望根据您的条件更新电子邮件具有最大匹配数的故障单中的一行。
我认为这是您想要的查询:
UPDATE `tickets` t JOIN
(SELECT `email`, max(matches) as maxm
FROM tickets t
WHERE `date` BETWEEN '$weekstart' AND '$weekend' AND `matches` >= 3
GROUP BY email
ORDER BY maxm DESC
LIMIT 1
) te
ON t.email = t3.email
SET t `winner` = 'Y'
LIMIT 1;
您可能希望使用此order by
:
order by maxm DESC, rand()
答案 2 :(得分:0)
试试这个:
UPDATE tickets
INNER JOIN (
SELECT `ticketid`
FROM `tickets`
WHERE `date` BETWEEN '$weekstart'
AND '$weekend' AND `matches`>='3'
ORDER BY `matches` DESC LIMIT 1) t
ON tickets.ticketid = t.ticketid
SET `winner`='Y'