SQL Server:查找每个用户购买的最受欢迎的产品类别,以便在子查询中使用

Sch*_*zIT 4 sql sql-server

我有三个表:categories(id,name),products(id,category_id,name))和purchases(id,user_id,product_id).A product属于category.用户可以购买很多products.我的目的是找到category每个用户最受欢迎的.

但是,我需要使用查询的结果集作为子查询,因此ORDER BY由于SQL Server限制(可怕的The ORDER BY clause is invalid in views, inline functions, derived tables, and subqueries, unless TOP is also specified.错误),不幸地使用任何语句都是关闭的.

我的方法是创建purchases每个用户的列表category.然后我有一个MAX功能来挑选出最大数量的purchases.我将结果连接到原始查询(复制为子查询)以检索有category_id问题,最后我获取类别名称.

我的查询有两个问题:

  1. 显然,我不希望在我的代码中两次使用相同的查询.但是,我不能依赖于使用CTE或临时表,因为此查询的结果旨在链接到具有用户数据子集的视图,并且VIEW代码旨在用于第三个-party包,只能处理基本的SQL代码.
  2. 如果出现平局(比如说,一个玩家买了4个products,2个来自2 categories个),我最终会为该用户重复一行.

小提琴:

http://sqlfiddle.com/#!6/8821b/5

如果有人能够帮助我找到确保每个用户只返回一行的方法,以及删除重复子查询的方法,我将不胜感激.

谢谢!

Jim*_* V. 5

首先,感谢您在SQLFiddle中提供示例.它使ALOT更容易帮助.

您可以使用row_number更精确地获取"顶级"记录.在此示例中,我选择在计数后使用category_name作为辅助排序条件.

SELECT user_id, category_name, category_count
FROM
(
  SELECT 
      user_id, COUNT(1) as category_count, category_name, 
      ROW_NUMBER() OVER (
          PARTITION BY user_id 
          ORDER BY COUNT(1) DESC, category_name ASC) 
          as ordinal_position
  FROM
      purchases p 
          JOIN products p2 ON p.product_id = p2.id
          JOIN categories c ON p2.category_id = c.id        
  GROUP BY user_id, category_name
 ) a
WHERE ordinal_position = 1
ORDER BY category_count DESC
Run Code Online (Sandbox Code Playgroud)

SQL Fiddle的例子.