我创建了两个视图来帮助计算user_diary_number,然后选择日记号为>的用户。总用户的user_diary_number的平均值。
两个观点如下:
create view user_diary_number as
(
select user_id,count( distinct diary_id ) as diary_num
from user_diary
group by user_id
);
,第二次使用having
和avg
:
create view hw_diary as
(
select u.user_id, u.realname, ud.diary_num, school.school_name
from (user as u cross join user_diary_number as ud on u.user_id = ud.user_id )cross join school on u.school_id = school.school_id
having diary_num > avg(diary_num)
);
现在问题是,第二个视图只有1行结果。并且绝对地,我们有超过1个用户,其日记号>平均diary_num。实际上,我总共有251个日记和103个用户。一些用户有9,4,5日记。 但结果只有1个用户有3本日记。
我的相关表格是:
CREATE TABLE IF NOT EXISTS `school` (
`school_id` int(11) NOT NULL,
`school_name` varchar(45) NOT NULL,
`location` varchar(45) NOT NULL,
`master` varchar(45) NOT NULL,
`numbers_of_student` int(11) NOT NULL,
PRIMARY KEY (`school_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `user_diary` (
`diary_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`title` varchar(45) NOT NULL,
`content` varchar(255) NOT NULL,
`addtime` DATETIME NOT NULL,
PRIMARY KEY (`diary_id`,`user_id`),
KEY `fk_diary_user_id_idx` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
交叉加入有问题吗?或者是其他东西? 非常感谢!
答案 0 :(得分:3)
你不能这样使用avg。在我的个人电影数据库中,
select * from movie having year > avg(year);
什么都不产生,
select * from movie having year > (select avg (year) from movie);
产生预期结果。
答案 1 :(得分:1)
您必须在单独的子查询中计算平均值。
类似的东西:
select ...
from ...
group by ...
having diary_num > (
select avg(diary_num)
from ...)
你可以填写有意义的空白
答案 2 :(得分:1)
这样的东西应该返回你正在寻找的结果集:
SELECT u.user_id
, u.realname
, c.diary_num
, s.school_name
-- , a.diary_avg
FROM ( SELECT d.user_id
, COUNT(DISTINCT d.diary_id) AS diary_num
FROM user_diary d
) c
JOIN user u
ON u.user_id = c.user_id
JOIN school s
ON s.school_id = u.school_id
JOIN ( SELECT AVG(v.diary_num) AS diary_avg
FROM ( SELECT t.user_id
, COUNT(DISTINCT t.diary_id) AS diary_num
FROM user_diary t
) v
) a
ON a.diary_avg < c.diary_num
ORDER BY 1
作为c
别名的内联视图为我们提供每个用户的diary_num(计数)。
作为a
别名的内联视图获取所有用户的所有diary_num的平均值。这让我们得到了计数的“平均值”,这就是原始查询打算做的事情。
作为替代方案,我们可以将每个用户的“平均”日记数量作为...所有日记的总数除以所有用户的总数。为此,请使用以下内容替换为a
别名的内联视图:
( SELECT COUNT(DISTINCT t.diary_id)
/ NULLIF(COUNT(DISTINCT v.user_id),0) AS diary_avg
FROM user v
LEFT
JOIN user_diary t
ON t.user_id = v.user_id
) a
这会产生略微不同的结果,因为它是对总计数的计算,而不是计算的平均值。
注意强>
CROSS
关键字对MySQL优化器没有影响。
我们通常会将CROSS
关键字作为未来审核人员的文档。它表明我们有目的地省略了通常的ON
子句。 (作为一个修订版,当我们看到一个没有ON条款的JOIN时,我们的思想会竞争“可能的非预期笛卡尔产品”......作者包含CROSS
关键字提醒我们(评论者)忽略ON
条款是有目的的。
但MySQL优化器并不关心是否包含CROSS
关键字。
还有一个问题:MySQL是否支持“View的SELECT包含FROM子句中的子查询”?
答: MySQL的旧版本(3.x?)不支持子查询。但当然,MySQL 5.1及更高版本确实支持子查询。
要回答您的问题,是的,SELECT语句可以用作内联视图作为另一个查询的行源,例如
SELECT v.*
FROM (
SELECT 1 AS foo
) v