SQL 数据多级分类排序:拥有者、类别及子类别高效排序
2024-12-18 05:11:17
SQL 数据结果按拥有者、类别和子类别排序
在使用 SQL 查询数据库时,经常需要根据特定条件对数据进行排序。当数据涉及拥有者、类别和子类别等多级分类时,如何实现高效且准确的排序成为一个关键问题。针对根据拥有者、类别和子类别进行排序,下面将探讨几种有效的解决思路及对应操作。
一、 问题解析
核心需求是按层级对数据排序。 顺序为拥有者(owner_id)、类别(category_id)、子类别(subcategory_id)。原始 SQL 查询使用 CASE
语句,意图实现对不同类别和子类别的排序。 问题在于这种方法需要预先定义每个类别和子类别的对应关系, 增加了维护难度且降低灵活性。
二、 优化方案
解决该问题有两种推荐的方案。
1. 创建排序辅助列
通过增加一个排序辅助列。 为不同分类逻辑赋予数字,以建立清晰的优先级关系,然后通过多列排序解决。
-
原理 :将分类信息映射为连续的整数值。通过辅助列,可以简化
ORDER BY
子句, 使其更加清晰易懂, 从而摆脱繁琐的CASE
语句。 -
操作步骤 :
- 修改表结构, 添加新的
sort_order
字段。 可将这个操作通过更新语句临时放在虚拟表格, 不一定要更改数据表格本身。 - 通过类似以下规则的方式更新此字段。 通过一个辅助字段来规范化原本通过多个case 表达的内容。
category_id = 1 AND subcategory_id = 1
设置为 1category_id = 1 AND subcategory_id = 2
设置为 2category_id = 1 AND subcategory_id = 3
设置为 3category_id = 1 AND subcategory_id = 4
设置为 4category_id = 2 AND subcategory_id = 7
设置为 5category_id = 2 AND subcategory_id = 8
设置为 6category_id = 2 AND subcategory_id = 9
设置为 7category_id = 1 AND subcategory_id = 17
设置为 8category_id = 1 AND subcategory_id = 18
设置为 9category_id = 1 AND subcategory_id = 19
设置为 10- 其他情况 设置为 11
- 使用
ORDER BY
进行多列排序。
- 修改表结构, 添加新的
-
代码示例 :
SELECT t.*
FROM (
SELECT
*,
CASE
WHEN (category_id = 1 AND subcategory_id = 1) THEN 1
WHEN (category_id = 1 AND subcategory_id = 2) THEN 2
WHEN (category_id = 1 AND subcategory_id = 3) THEN 3
WHEN (category_id = 1 AND subcategory_id = 4) THEN 4
WHEN (category_id = 2 AND subcategory_id = 7) THEN 5
WHEN (category_id = 2 AND subcategory_id = 8) THEN 6
WHEN (category_id = 2 AND subcategory_id = 9) THEN 7
WHEN (category_id = 1 AND subcategory_id = 17) THEN 8
WHEN (category_id = 1 AND subcategory_id = 18) THEN 9
WHEN (category_id = 1 AND subcategory_id = 19) THEN 10
ELSE 11
END as sort_order
FROM transactions
WHERE is_submitted = 0
) as t
ORDER BY
owner_id,
sort_order,
receipt_date;
- 安全建议 : 创建 sort_order 列需要谨慎设置,需要保持数据一致。 当涉及到新增内容时要更新相应的序号逻辑,以免出现排序问题。 如果没有更改表的权限可以尝试利用临时表或子查询创建临时
sort_order
列。
2. 建立映射表
可以考虑引入一个专门的映射表来存储类别、子类别和排序值之间的对应关系。 方案一的 case 内容可以被这个表的逻辑所替代。
-
原理 :使用映射表可以将排序逻辑与业务数据解耦。 查询时通过表连接
JOIN
获取对应的排序值,从而避免了在每个查询中都编写复杂的CASE
语句, 也免除了为每个表添加 sort_order 辅助列的需求。 -
操作步骤 :
-
创建一个新的映射表
category_sort_order
, 包含以下字段:category_id
,subcategory_id
,sort_order
。 -
在该表中添加如下数据。
category_id subcategory_id sort_order 1 1 1 1 2 2 1 3 3 1 4 4 2 7 5 2 8 6 2 9 7 1 17 8 1 18 9 1 19 10 -
将
transactions
表与此表关联进行查询。
-
-
代码示例 :
SELECT t.*
FROM transactions t
LEFT JOIN category_sort_order cso ON t.category_id = cso.category_id AND t.subcategory_id = cso.subcategory_id
WHERE t.is_submitted = 0
ORDER BY
t.owner_id,
cso.sort_order,
t.receipt_date;
- 安全建议 : 对
category_sort_order
表做好读写权限控制, 只允许少数必要的人对这个表的内容进行更改。 可以通过外键约束确保transactions
表与category_sort_order
表中的数据一致性。 在数据量比较大的情况下, 提前设计好表的索引能优化查询速度。