首先,我要感谢您:
这是作业,所以我绝不是在要求答案,只是一些
指导!
还有这个:
由于这是作业,请不要回答,只是寻求指导
尽你所能。
我将尝试做的是给你一些提示,引导你找到答案。
(根据给定的信息)我假设这个作业将使用聚合函数(例如 SUM()、AVG()、MIN()、MAX() ..etc)、GROUP BY、(可能是 HAVING)和订购人。
请记住,无论何时使用聚合函数,都需要指定 SELECT 下的列,并且它们不包含在 GROUP BY 子句中的聚合函数中。
所以,如果你这样做了:
SELECT t.pub_id, SUM(((price - (royalty * 1.0 / 100)) * ytd_sales) - advance), t.pubdate
FROM titles AS t
GROUP BY t.title;
它会给你一个错误,因为 SELECT 子句下没有t.title。所以,正确的应该是这样的:
GROUP BY t.pub_id, t.pubdate
如果你希望它按 t.title 分组,你需要这样做:
SELECT t.title, SUM(((price - (royalty * 1.0 / 100)) * ytd_sales) - advance)
FROM titles AS t
GROUP BY t.title;
如果有规定的时间段(假设您想获得每个标题最近 3 个月的利润),那么您可以使用 t.pubdate 但这将在 WHERE(或 HAVING)子句下,并且t.title 将在 SELECT 子句下。
现在,完成计算后,您需要按最高利润对结果重新排序,然后选择最高利润。有些人喜欢更容易包含两个聚合函数(比如 MIN(SUM(...)) )来获得最高或最低,这将避免他们使用 ORDER BY。
更新(基于 cmets)
由于您已经介绍了子查询,因此您非常接近答案。
运行第二个标题查询后,我可以看到所有
头衔和他们的利润,我似乎无法弄清楚如何关联
这些标题及其相应的 pub_id。假设我有 3
pub_id's - 每个 pub_id 有多个标题。我不知道怎么做
关联特定 pub_id 的 top_profit 标题,如果那样的话
有道理。
获取利润的正确方法是找到可以用来汇总利润的唯一 ID。对于您的情况,您说 pub_id 有多个 title 然后,我假设 pub_id 是主键,并且标题被分配给每个主键。 (例如,一个出版商可以出版多本书)所以你需要从所有出版的书籍中获得出版商的利润。
有了这个,您就知道您需要的是出版商而不是书籍。因此,在您的查询中,您需要将 titles 替换为 pub_id 并保持其余部分不变。这将根据pub_id 总结所有利润,这是您需要的主要要求。
如果你需要为每个出版商的书获取利润,你可以使用
SELECT t.pub_id, t.title SUM(....) as Profit
FROM titles AS t
GROUP BY t.pub_id, t.title;
这就像告诉 SQL :嘿,给我每本书的出版商利润。这将为您带来每本书的利润。
但如果你这样做:
SELECT t.pub_id, SUM(....) as Profit
FROM titles AS t
GROUP BY t.pub_id;
它会为您提供每个出版商的利润(这意味着如果出版商有 5 本书,则将其相加)。
因此,GROUP BY 中包含的列越多,SUM() 中的列就越详细。
如果您需要用子查询将其括起来,有不同的方法可以做到这一点,但我会给您两种方法。
方法一:
SELECT *
FROM (
SELECT t.pub_id, SUM(....) as Profit
FROM titles AS t
GROUP BY t.pub_id;
) D -- alias is mandatory
方法二:
SELECT *
FROM titles t1
JOIN (
SELECT t.pub_id, SUM(....) as Profit
FROM titles AS t
GROUP BY t.pub_id;
) t2 ON t1.pub_id = t2.pub_id
因此,您可以使用方法一或方法二,随心所欲。
更新(基于 cmets)#2
我已经添加了我目前所获得的屏幕截图 - 它看起来不错。
如您所见,每个 pub_id 都有多个标题 - 我怎么能
只返回 3 个 pub_id 中最赚钱的标题??
太好了,你快完成了。您需要使用名为ROW_NUMBER() 的函数根据我们的自定义条件对行进行编号。所以我们将添加这个:
ROW_NUMBER() OVER(PARTITION BY t1.pub_id ORDER BY Profit DESC) AS ProfitOrder
新订单将按 t1.pub_id 进行分区,并将每个分区按利润从高到低排序(对于每个 id 组)。
我们的查询应该是这样的:
SELECT
t1.title
, t1.pub_id
, t1.pubdate
, Profit
, ROW_NUMBER() OVER(PARTITION BY t1.pub_id ORDER BY Profit DESC) AS ProfitOrder
FROM titles t1
JOIN (
SELECT t.pub_id, t.title, SUM(price * ytd_sales) as Profit
FROM titles AS t
GROUP BY t.pub_id
) t2 ON t1.pub_id = t2.pub_id
如果您运行上面的查询,每个 pub_id 的 ProfitOrder 编号 1 将具有最高的 Profit,这将验证我们的记录是否正确排序,我们只需要使用 ProfitOrder 从每个组中获取前 3 行。
如果我们需要这样做:
SELECT
t1.title
, t1.pub_id
, t1.pubdate
, Profit
, ROW_NUMBER() OVER(PARTITION BY t1.pub_id ORDER BY Profit DESC) AS ProfitOrder
FROM titles t1
JOIN (
SELECT t.pub_id, t.title, SUM(price * ytd_sales) as Profit
FROM titles AS t
GROUP BY t.pub_id
) t2 ON t1.pub_id = t2.pub_id
WHERE
ProfitOrder <= 3
它会产生错误,因为我们不能在WHERE 下使用列别名,除非我们将查询转换为子查询。因此,我们需要(再次)将此查询包含在子查询中。喜欢这个:
SELECT *
FROM (
SELECT
t1.title
, t1.pub_id
, t1.pubdate
, Profit
, ROW_NUMBER() OVER(PARTITION BY t1.pub_id ORDER BY Profit DESC) AS ProfitOrder
FROM titles t1
JOIN (
SELECT t.pub_id, t.title, SUM(price * ytd_sales) as Profit
FROM titles AS t
GROUP BY t.pub_id
) t2 ON t1.pub_id = t2.pub_id
) D
WHERE
ProfitOrder <= 3
现在,如果输出符合您的预期,请再次验证记录。然后,您只需要使用顶部的SELECT * 并选择您只需要显示的列。 LIKE SELECT pub_id, Profit, pubdate,并将其包含在您的 INSERT 下,但请确保您匹配 INSERT 和您的 SELECT 之间的列。