行号为()的SQL查询未返回预期输出
我的目标是编写一个查询,返回每个商品类别平均销售额最高的城市 这是预期输出:行号为()的SQL查询未返回预期输出,sql,Sql,我的目标是编写一个查询,返回每个商品类别平均销售额最高的城市 这是预期输出: item_category|city books |los_angeles toys |austin electronics |san_fransisco 我的3个表模式如下所示: users user_id|city sales user_id|item_id|sales_amt items item_id|item_category 这些是需要考虑的进一步注意事项: 1.sa
item_category|city
books |los_angeles
toys |austin
electronics |san_fransisco
我的3个表模式如下所示:
users
user_id|city
sales
user_id|item_id|sales_amt
items
item_id|item_category
这些是需要考虑的进一步注意事项:1.sales_amt是唯一可能有空值的列。如果没有用户为特定商品类别进行销售(销售中没有非空销售金额的行),则城市名称应为空。
2.每个不同的项目仅1行。如果超过1个城市符合条件,则按字母顺序选择第一个城市 我所做的尝试如下所示,但没有产生正确的输出:
select a.item_category,a.city from (
select
i.item_category,
u.city,
row_number() over (partition by i.item_category,u.city order by avg(s.sales_amt) desc)rk
from sales s
join users u on s.user_id=u.user_id
join items i on i.item_id=s.item_id
group by i.item_category,u.city)a
where a.rk=1
我的输出不返回销售金额的空案例。此外,我还得到了非唯一行。因此,我非常紧张,因为我没有正确地合并这两个音符
我希望有人能帮上忙。我想您希望
在内部查询中从users
开始加入s,以保留没有销售的城市
至于排名:如果您希望每个城市有一条记录,那么不要将该城市的其他列放在分区中(您当前的分区为每个城市和每个类别提供一条记录,这不是您想要的)
考虑:
select *
from (
select
i.item_category,
u.city,
rank() over(partition by u.city order by avg(s.sales_amt) desc) rk
from users u
left join sales s on s.user_id = u.user_id
left join items i on i.item_id = s.item_id
group by i.item_category, u.city
) t
where rk = 1
我的目标是编写一个查询,返回每个商品类别平均销售额最高的城市
这可以使用聚合和窗口函数进行计算:
select ic.*
from (select i.item_category, u.city,
row_number() over(partition by u.item_category order by avg(s.sales_amt) desc, u.city) as seqnum
from users u join
sales s
on s.user_id = u.user_id join
items i
on i.item_id = s.item_id
group by i.item_category, u.city
) ic
where seqnum = 1;
您的问题明确表示“平均”,这就是为什么它使用avg()
。然而,我怀疑你真的想要每个城市的总和,那就是sum()
注:
- 您需要一行,因此
行号()
而不是秩()
- 您需要sales来计算平均值,因此
join
,而不是left join
- 您希望每个项目\类别有一行,以便用于分区
aa我对它的看法是GMB和戈登的建议的混合;GMB指出需要左连接,但我认为他的起始表、分区和rank()的选择是错误的(他的查询无法按请求生成空城市名称,并且可能会生成绑定在同一个avg上的重复项),Gordon学习了一些东西,比如按城市在绑定的avg上排序,GMB没有,但错过了“如果X类商品没有销售,则该城市将为空”要求。两人都将取消的订单留在系统中,这会导致错误:
select *
from (
select
i.item_category,
u.city,
row_number() over(partition by i.item_category order by avg(s.sales_amt) desc, u.city asc) rn
from items i
left join (select * from sales where sale_amt is not null) s on i.item_id = s.item_id
left join users u on s.user_id = u.user_id
group by i.item_category, u.city
) t
where rn = 1
我们从itemcategory开始,这样没有销售额的类别的销售额和城市都会为空
我们还需要考虑的是,任何未完成的销售在数量上都是空的,我们用一个子查询排除它们,否则它们会链接到用户给出一个假阳性-即使AVG将只计算一个只取消订单的类别,该城市仍然会显示它不应该出现的时候。我们使用
和sales\u amt在连接中不为null的谓词来实现这一点,但我认为这种方式更清晰。不应该使用where子句中的谓词来实现这一点,因为这将消除我们试图保留的sale-less类别
行数用于avg,但与城市名称一起用于断开任何联系。它是一个比rank更简单的函数,不能生成重复值
最后,我们拉rn 1得到最高平均城市数为什么还要按城市划分行数?实际上,你希望行数只在一个类别内增加,平均值最高的是1,然后从中得到城市数。如果你也按城市划分,那么每个城市都将排名1,你是说如果你没有r销售商品X它在销售中会有一个记录,金额为空?这很奇怪。我本以为商品表会有一个记录X,但销售表中没有X的行“每个商品只有一行”-你是说“商品类别”吗“?@CaiusJard感谢您的反馈。回答:我可能不需要像你说的那样按城市划分,因为我可以按城市和item_cat分组以获得结果。销售金额为空的原因是当客户为某个项目X下订单,但该项目不再有库存时(仓库同步延迟)。是的,我希望每个商品类别和城市都有一行(平均销售额最高)。您使用的是哪种RDBMS?你已经标记了三个。。。