行号为()的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?你已经标记了三个。。。