在搜索并阅读了一点之后,我为我的应用程序提出了以下SQL查询:
SELECT
ROUND(AVG(CASE WHEN gender = 'M' THEN rating END), 1) avgAllM,
COUNT(CASE WHEN gender = 'M' THEN rating END) countAllM,
ROUND(AVG(CASE WHEN gender = 'F' THEN rating END), 1) avgAllF,
COUNT(CASE WHEN gender = 'F' THEN rating END) countAllF,
ROUND(AVG(CASE WHEN gender = 'M' AND UserAge(birth_date) <= 18 THEN rating END), 1) avgU18M,
COUNT(CASE WHEN gender = 'M' AND UserAge(birth_date) <= 18 THEN rating END) countU18M,
ROUND(AVG(CASE WHEN gender = 'F' AND UserAge(birth_date) <= 18 THEN rating END), 1) avgU18F,
COUNT(CASE WHEN gender = 'F' AND UserAge(birth_date) <= 18 THEN rating END) countU18F
FROM movie_ratings mr INNER JOIN accounts a
ON mr.aid = a.aid
WHERE mid = 5;
我想知道如果可能的话我该如何简化呢。 birth_date
字段的类型为DATE
,UserAge
是计算该日期字段的年龄的函数。
表格结构如下:
[ACCOUNTS]
aid(PK), birth_date, gender
[MOVIE_RATINGS]
mid(PK), aid(PK,FK), rating
我正在寻找两件事:
例如,像这样:
$info[0]['avgAllM']
$info[0]['countAllM']
$info[1]['avgAllF']
$info[1]['countAllF']
$info[2]['avgU18M']
$info[2]['countU18M']
$info[3]['avgU18F']
$info[3]['countU18F']
而不是:
$info['avgAllM']
$info['countAllM']
$info['avgAllF']
$info['countAllF']
$info['avgU18M']
$info['countU18M']
$info['avgU18F']
$info['countU18F']
我甚至不知道这是否可能,所以我真的很想知道它是否可以以及如何做到。
为什么我要这一切?好吧,上面的SQL查询只是我需要做的完整SQL的一个片段。我还没有完成它,因为在完成所有工作之前,我想知道是否有更紧凑的SQL查询来实现相同的结果。基本上我会添加一些像上面那些但具有不同条件的行,特别是在日期。
答案 0 :(得分:3)
您可以使用以下定义创建VIEW
SELECT
CASE WHEN gender = 'M' THEN rating END AS AllM,
CASE WHEN gender = 'F' THEN rating END AS AllF,
CASE WHEN gender = 'M' AND UserAge(birth_date) <= 18 THEN rating END AS U18M,
CASE WHEN gender = 'F' AND UserAge(birth_date) <= 18 THEN rating END AS U18F
FROM movie_ratings mr INNER JOIN accounts a
ON mr.aid = a.aid
WHERE mid = 5
然后从
中选择SELECT ROUND(AVG(AllM), 1) avgAllM,
COUNT(AllM) countAllM,
ROUND(AVG(AllF), 1) avg,
COUNT(AllF) countAllF,
ROUND(AVG(U18M), 1) avgU18M,
COUNT(U18M) countU18M,
ROUND(AVG(U18F), 1) avgU18F,
COUNT(U18F) countU18F
FROM yourview
可能会略微简化一下吗?
答案 1 :(得分:0)
这可能只是过早优化的情况。查询可以满足您的需求,但实际上看起来非常复杂。我不确定是否一定有任何有用的技巧。它可能取决于您的数据的特征。查询速度慢吗?你觉得它会更快吗?
可能值得以下列方式重新排列。由于所有条件都依赖于ACCOUNTS
表,我假设该表明显小于MOVIE_RATINGS
表,因此您可以对较小的数据集进行所有计算,这可能会更快。虽然如果你一次只选择一部电影(mid = 5
),那么可能情况并非如此。
我不完全确定这会有效,但我认为应该这样做。
SELECT
ROUND(AVG(rating * AllM), 1) avgAllM,
COUNT(rating * AllM) countAllM,
ROUND(AVG(rating * AllF), 1) avgAllF,
COUNT(rating * AllF) countAllF,
ROUND(AVG(rating * AllM * U18), 1) avgU18M,
COUNT(rating * AllM * U18) countU18M,
ROUND(AVG(rating * AllM * U18), 1) avgU18F,
COUNT(rating * AllM * U18) countU18F
FROM
movie_ratings mr
INNER JOIN (
select
aid,
case when gender = 'M' then 1 end as AllM,
case when gender = 'F' then 1 end as AllF,
case when UserAge(birth_date) <= 18 then 1 end as U18
from accounts) a ON mr.aid = a.aid
WHERE mid = 5;
总的来说,我可能只是保留你的查询。您拥有的查询很容易理解,并且可能表现得相当不错。