简体   繁体   English

在 SQL 中转置/旋转数据

[英]Transposing/Pivoting Data in SQL

I'm sorry to ask yet another question that pertains to this topic—I read through the other threads but I still can not figure out my specific case.很抱歉再问一个与该主题相关的问题——我通读了其他线程,但仍然无法弄清楚我的具体情况。

So I have an output:所以我有一个 output:

在此处输入图像描述

The query that outputs the above is:输出上述内容的查询是:

SELECT  (CASE
            WHEN ca.iteration = 'Pre' THEN '1. Pre'
            WHEN ca.iteration = 'Post-2' THEN '3. Post-2'
            WHEN ca.iteration = 'Post' THEN '2. Post'
            END) AS capes_iteration,
           ROUND(AVG(ca.emotional_problems_score)) AS avg_child_emotions_score,
           ROUND(AVG(ca.behavioral_problems_score)) AS avg_child_behaviors_score,
           ROUND(AVG(ca.total_score)) AS avg_total_intensity_score,
           ROUND(AVG(ca.total_parent)) AS avg_parent_confidence_score
     FROM  reporting_f5scppp.capes ca
LEFT JOIN  public.contacts c ON c.id = ca.contact_id
 GROUP BY  capes_iteration;

What I want it to look like is this:我希望它看起来像这样:

在此处输入图像描述

I've spent about 4 hours trying to get this to no avail—I'm only a beginner to SQL—seeing a solution to this will be a great learning opportunity for me.我花了大约 4 个小时试图解决这个问题——我只是 SQL 的初学者——看到这个问题的解决方案对我来说是一个很好的学习机会。

If anyone can provide a simple solution—lunch is on me!如果有人能提供一个简单的解决方案——午餐在我身上!

You can unpivot the scores using a lateral join.您可以使用横向连接取消透视分数。 Then just reaggregate:然后重新聚合:

SELECT v.which,
       AVG(v.score) FILTER (WHERE ca.iteration = 'Pre') as avg_1_pre,
       AVG(v.score) FILTER (WHERE ca.iteration = 'Post-2') as avg_3_post_2,
       AVG(v.score) FILTER (WHERE ca.iteration = 'Post') as avg_2_post
FROM reporting_f5scppp.capes ca LEFT JOIN
     public.contacts c
     ON c.id = ca.contact_id LEFT JOIN LATERAL
     (VALUES (emotional_problems_score, 'emotional'),
             (behavioral_problems_score, 'behaviors'),
             (total_score, 'intensity'),
             (total_parent, 'parent')
     ) v(score, which)
GROUP BY  v.which;

One option would be unpivoting by using each() function in order to get key-value tuples, and then pivoting by conditional aggregation in the main query:一种选择是通过使用each() function 来获取键值元组,然后在主查询中通过条件聚合进行旋转:

SELECT (kv).key AS capes_iteration, 
       MAX(CASE WHEN iteration = 'Pre' THEN (kv).value END) AS "1. Pre",
       MAX(CASE WHEN iteration = 'Post-2' THEN (kv).value END) AS "3. Post-2",
       MAX(CASE WHEN iteration = 'Post' THEN (kv).value END) AS "2. Post"
  FROM
  (
   SELECT iteration, each(hstore(q) - 'iteration'::text) AS kv
     FROM (
           SELECT iteration,
                  ROUND(AVG(COALESCE(ca.emotional_problems_score,0))) AS avg_child_emotions_score,
                  ROUND(AVG(COALESCE(ca.behavioral_problems_score,0))) AS avg_child_behaviors_score,
                  ROUND(AVG(COALESCE(ca.emotional_problems_score,0)+
                            COALESCE(behavioral_problems_score,0))) AS avg_total_intensity_score,
                  ROUND(AVG(ca.total_parent)) AS avg_tot_parent_confidence_score
             FROM capes ca
             LEFT JOIN  contacts c ON c.id = ca.contact_id
            GROUP BY  iteration ) q ) q2
 GROUP BY capes_iteration
 ORDER BY capes_iteration

where在哪里

  • use COALESCE() function with zero as the second argument to assign the null values to zero使用COALESCE() function 零作为第二个参数将 null 值分配为零
  • notice that avg_total_intensity_score is a derived column from addition of two columns请注意, avg_total_intensity_score是从添加两列的派生列

Demo 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM