题
搜索和阅读后,我想到了我的应用程序以下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
我正在寻找两件事:
- 对上述代码的一般简化,更有经验的用户知道我不知道。
- 我正在使用PHP进行此操作,对于每个记录,我都会有一个与所有这些变量的关联阵列。我正在寻找一种将它们分组为多维数组的方法,因此PHP代码易于阅读。当然,我不想在PHP本身中这样做,这将是毫无意义的。
例如,这样的事情:
$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查询以实现相同的结果。基本上,我将添加其他类似上述线的行,但有不同的条件,特别是在日期。
解决方案
您可以创建一个 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
可能会稍微简化事情吗?
其他提示
这可能只是优化过早的情况。该查询可以完成您需要的工作,并且只是看起来很复杂,因为它确实很复杂。我不确定是否有任何技巧会有所帮助。这可能取决于数据的特征。查询慢吗?您认为可能会更快吗?
可能值得以以下方式重新安排它。由于所有条件都取决于 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;
不过,总而言之,我可能只会离开您的查询。您拥有的查询易于理解,并且可能表现良好。
不隶属于 StackOverflow