我有3个表:alert,user_to_alert和user_device。设备表包含一个令牌列表,并包含一个user_id字段。
user_to_alert表保存用户何时读取警报的记录。如果相应的alert_id / user_id组合不存在记录,则表示用户尚未读取警报。还有一个alert_read列可以为零(如果用户在阅读后将警报标记为未读)。
我有一个加载设备令牌列表的查询,我需要展开它以包含未读警报的数量。这是我提出的查询
SELECT d.*, (
SELECT COUNT(*) FROM `alert` AS a
LEFT JOIN `user_to_alert` AS uta ON
( uta.`alert_id` = a.`alert_id` AND uta.`user_id` = d.`user_id` )
WHERE uta.`alert_read` = 0 OR uta.`alert_read` IS NULL) AS user_badge_number
FROM `user_device` AS d
WHERE d.`device_type` = 'iOS' AND d.`device_active` = 1
GROUP BY d.`device_token`
此查询错误#1054 - Unknown column 'd.user_id' in 'on clause'
我已经使用架构和查询设置了一个SQLFiddle:http://sqlfiddle.com/#!9/ee653/2
如果我单独运行我的子查询并用d.user_id替换有效的user_id,我会得到预期的结果(即user_id 10为3)。我认为这意味着问题出在我引用列d.user_id的地方。我想MySQL首先尝试执行子查询,所以d.user_id不是一个有效的列呢?这只是一个猜测。
我已经尝试将我的ON子句的uta.user_id = d.user_id
部分移动到WHERE子句,但是只为user_badge_number列提供了所有行。
我无法通过Google查找与此问题相关的任何内容。我发现关于相关子查询的所有内容似乎都在ON或WHERE子句中使用它们,而不是使用它们来检索额外的数据。
这是通过PHP脚本运行的,所以我知道我可以在PHP脚本的结果循环中自己运行子查询。显然,我宁愿弄清楚如何使用一个查询来实现它,因为这会更有效。
答案 0 :(得分:0)
它是相关子查询中的范围问题,请尝试使用表名
SELECT d.*, (
SELECT COUNT(*) FROM `alert` AS a
LEFT JOIN `user_to_alert` AS uta ON
( uta.`alert_id` = a.`alert_id`)
WHERE uta.`user_id` = d.`user_id` AND
(uta.`alert_read` = 0 OR uta.`alert_read` IS NULL))
AS user_badge_number
FROM `user_device` AS d
WHERE d.`device_type` = 'iOS' AND d.`device_active` = 1
GROUP BY d.`device_token`
答案 1 :(得分:0)
正如您所指出的,不难计算读取的警报数量。您可以从总警报中减去该数字以获取未读数字:
SELECT d.*,
( SELECT COUNT(*) FROM `alert` ) -
( SELECT COUNT(*) FROM `user_to_alert`
WHERE `user_id` = d.`user_id` AND `alert_read` = 1 )
FROM `user_device` AS d
WHERE d.`device_active` AND d.`device_type` = 'iOS';
但请注意,设计存在问题,即如果在6个月后添加设备或用户,则过去的所有警报都将在该新设备上显示为未读。如果将设备重新分配给新用户,或者现有用户切换设备,则存在类似问题(取决于您是否计算未读警报每个用户或每个设备)。
为了解决这个问题,您可以将查询限制在特定日期范围9,因为添加了用户或设备,但是如果设备被重新分配,则不清楚使用的日期。)我认为更简单的答案是在创建每个警报时将行插入user_to_alert
。这有几个好处: