SQL:以长格式对数据进行计算的有效方法

时间:2018-06-05 09:40:16

标签: sql oracle oracle12c

我有一个按项目分列的男性和女性表格,如:

enter image description here

我希望按项目计算男性的比例,这样输出看起来像:

ITEM  PROP_MALE
A     0.3
B     0.5

在R中,我会将dcast性别划分为宽格式,然后在男性同一行中将男性人数除以总数。但是在SQL中,我很难找到一个有效的解决方案(如果它有帮助,我使用的是Oracle SQL)。

4 个答案:

答案 0 :(得分:1)

我会简单地使用http://www.brajesh.com/tagsDef和除法:

sum()

答案 1 :(得分:0)

您可以使用RATIO_TO_REPORT

SELECT ITEM, PROP_MALE
FROM  (SELECT ITEM, gender,
       RATIO_TO_REPORT(N) OVER (PARTITION BY Item) AS PROP_MALE
      FROM tab) sub
WHERE sub.gender = 'M';

<强> DBFiddle Demo

答案 2 :(得分:0)

您可以使用SUM分析函数:

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE table_name ( item , gender, n ) AS
SELECT 'A', 'M',  30 FROM DUAL UNION ALL
SELECT 'A', 'F',  70 FROM DUAL UNION ALL
SELECT 'B', 'M', 100 FROM DUAL UNION ALL
SELECT 'B', 'F', 100 FROM DUAL;

查询1

SELECT Item,
       n / total AS prop_male
FROM   (
  SELECT t.*,
         SUM( n ) OVER ( PARTITION BY Item ) AS total
  FROM   table_name t
)
WHERE  gender = 'M'

<强> Results

| ITEM | PROP_MALE |
|------|-----------|
|    A |       0.3 |
|    B |       0.5 |

您甚至可以使用不计数值直接在表格上进行计算:

Oracle 11g R2架构设置

CREATE TABLE table_name_pre_count ( item , gender ) AS
SELECT 'A', 'M' FROM DUAL CONNECT BY LEVEL <=  30 UNION ALL
SELECT 'A', 'F' FROM DUAL CONNECT BY LEVEL <=  70 UNION ALL
SELECT 'B', 'M' FROM DUAL CONNECT BY LEVEL <= 100 UNION ALL
SELECT 'B', 'F' FROM DUAL CONNECT BY LEVEL <= 100;

查询2

SELECT Item,
       prop_male
FROM   (
  SELECT item,
         gender,
         COUNT(*) / SUM( COUNT(*) ) OVER ( PARTITION BY Item )
           AS prop_male
  FROM   table_name_pre_count
  GROUP BY Item, Gender
)
WHERE  gender = 'M'

<强> Results

| ITEM | PROP_MALE |
|------|-----------|
|    A |       0.3 |
|    B |       0.5 |

答案 3 :(得分:0)

create table gender
(
  item varchar(10),
  gender varchar(10),
  val decimal(3,1)
  );
 insert into gender values ('A','M',30) ;
 insert into gender values ('A','F',70) ;
 with cte as
(
  select item,val,gender,
  sum(val) over(order by val) as calc
  from gender
  ),
cte1 as 
  (
  select item,
  case when gender='M' then val/calc end as prop_male
  from cte)
  select * from cte1
  where PROP_MALE is not null