You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL实现鞋类多布尔属性对的聚合透视视图(可扩展方案)

可扩展的鞋类属性聚合透视表SQL实现方案

核心思路

要实现可扩展的属性交叉计数,关键是避免硬编码属性字段——通过将宽表转换为通用长表结构,再通过自连接完成两两属性的关联统计,新增属性时无需修改核心SQL逻辑。

步骤1:将宽属性表转换为长表

先把源表(假设表名为shoe_attributes)的每个布尔属性字段拆成prod_id、attribute_name、is_available的行结构,适配任意数量的属性:

WITH attribute_long AS (
    SELECT 
        prod_id,
        's_7' AS attribute_name,
        s_7 AS is_available
    FROM shoe_attributes
    UNION ALL
    SELECT 
        prod_id,
        'c_black' AS attribute_name,
        c_black AS is_available
    FROM shoe_attributes
    UNION ALL
    -- 新增属性时仅需追加UNION ALL语句
    SELECT 
        prod_id,
        't_shoes' AS attribute_name,
        t_shoes AS is_available
    FROM shoe_attributes
)

若使用支持UNPIVOT语法的数据库(如Oracle、SQL Server),可更简洁地避免硬编码:

WITH attribute_long AS (
    SELECT prod_id, attribute_name, is_available
    FROM shoe_attributes
    UNPIVOT (
        is_available FOR attribute_name IN (
            s_7, c_black, t_shoes -- 新增属性时仅需在此添加字段名
        )
    ) AS unpvt
)

步骤2:统计两两属性的同时可用计数

通过自连接长表,筛选出两个属性均为可用状态的prod_id,按属性对分组计数:

SELECT
    a.attribute_name AS attr1,
    b.attribute_name AS attr2,
    COUNT(DISTINCT a.prod_id) AS common_prod_count
FROM attribute_long a
JOIN attribute_long b 
    ON a.prod_id = b.prod_id
    AND a.is_available = 1
    AND b.is_available = 1
GROUP BY a.attribute_name, b.attribute_name

查询结果说明:

  • 当attr1与attr2相同时,得到的是该属性的总可用Prod_id数(对应透视表对角线数据)
  • 当attr1与attr2不同时,得到的是两个属性同时可用的Prod_id数

步骤3:转换为透视表格式(可选)

如果需要将结果转换为行列对应的透视表(类似Excel透视表),以MySQL为例,可用CASE语句实现:

WITH attribute_long AS (
    -- 复用步骤1的长表转换逻辑
    SELECT prod_id, attribute_name, is_available
    FROM shoe_attributes
    UNPIVOT (
        is_available FOR attribute_name IN (s_7, c_black, t_shoes)
    ) AS unpvt
),
cross_counts AS (
    SELECT
        a.attribute_name AS attr1,
        b.attribute_name AS attr2,
        COUNT(DISTINCT a.prod_id) AS common_prod_count
    FROM attribute_long a
    JOIN attribute_long b 
        ON a.prod_id = b.prod_id
        AND a.is_available = 1
        AND b.is_available = 1
    GROUP BY a.attribute_name, b.attribute_name
)
SELECT
    attr1,
    MAX(CASE WHEN attr2 = 's_7' THEN common_prod_count END) AS s_7,
    MAX(CASE WHEN attr2 = 'c_black' THEN common_prod_count END) AS c_black,
    MAX(CASE WHEN attr2 = 't_shoes' THEN common_prod_count END) AS t_shoes
    -- 新增属性时仅需追加对应的CASE语句
FROM cross_counts
GROUP BY attr1

性能优化建议

  • 给源表的prod_id字段创建主键或唯一索引,提升自连接的匹配效率
  • 为布尔属性字段创建复合索引(如(s_7, prod_id)),加快is_available=1的筛选速度
  • 若数据量持续增长,可预先计算长表并存储为中间表,定期刷新,避免每次查询都执行UNPIVOT操作

内容的提问来源于stack exchange,提问作者PavanV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 22:35:09