如何创建Access查询将表中多列转换为多行数据?
宽表转逆透视(行转列)解决方案
当然可以实现,你需要的是**逆透视(Unpivot)**操作——和CrossTab(透视/列转行)方向相反,把多列的纵向数据转换成多行的横向结构。以下是几种不同场景下的实现方式:
通用方法(所有数据库兼容)
如果你的数据库没有专用的逆透视语法,可以用UNION ALL逐个拆分列,适合列数较少的情况:
SELECT ID, 'SilverVAR' AS PartnerType, SilverVAR AS Discount FROM Discounts UNION ALL SELECT ID, 'GoldVAR' AS PartnerType, GoldVAR AS Discount FROM Discounts UNION ALL SELECT ID, 'PlatinumVAR' AS PartnerType, PlatinumVAR AS Discount FROM Discounts ORDER BY ID, PartnerType;
PostgreSQL专用优化方案
对于PostgreSQL,推荐用LATERAL JOIN结合VALUES,写法更简洁,扩展性也更好:
SELECT d.ID, t.PartnerType, t.Discount FROM Discounts d LATERAL ( VALUES ('SilverVAR', d.SilverVAR), ('GoldVAR', d.GoldVAR), ('PlatinumVAR', d.PlatinumVAR) ) t(PartnerType, Discount) ORDER BY d.ID, t.PartnerType;
如果后续新增合作类型列,只需要在VALUES里追加新的行即可。
SQL Server专用方案
SQL Server提供了UNPIVOT语法,专门处理这类需求:
SELECT ID, PartnerType, Discount FROM Discounts UNPIVOT ( Discount FOR PartnerType IN (SilverVAR, GoldVAR, PlatinumVAR) ) AS unpvt ORDER BY ID, PartnerType;
MySQL 8.0+动态适配方案
如果列数较多且可能频繁新增,可以用JSON_TABLE动态解析列数据:
SELECT d.ID, jt.PartnerType, jt.Discount FROM Discounts d JOIN JSON_TABLE( JSON_OBJECT( 'SilverVAR', d.SilverVAR, 'GoldVAR', d.GoldVAR, 'PlatinumVAR', d.PlatinumVAR ), '$.*' COLUMNS ( PartnerType VARCHAR(20) KEY PATH '$', Discount INT PATH '$' ) ) jt ORDER BY d.ID, jt.PartnerType;
列数较多时的扩展建议
如果后续会新增大量合作类型列,手动维护语句效率低,可以用动态SQL:通过查询系统表获取所有合作类型列名,自动生成逆透视语句。比如PostgreSQL中可以用information_schema.columns筛选列名拼接SQL。
内容的提问来源于stack exchange,提问作者Gary B
相关产品推荐
相关产品推荐

