2014-10-01 173 views
4

嗨我怎样才能得到每个记录在总数中的百分比? 让我们来想象我有以下SQL占总数的百分比

ID code Points 
1 101 2 
2 201 3 
3 233 4 
4 123 1 

ID 1的比例为20%230%等一个 我怎么得到它的一个表?

+2

您正在使用哪个DBMS? – DirkNM 2014-10-01 12:17:22

回答

1

尝试这样

select id,code,points,(points * 100)/(select sum(points) from tabel1) from table1 
+0

完美地工作谢谢 – Joaquim 2014-10-09 13:58:14

3

有几种方法可以得到那个结果。

你基本上需要整个表格(或任何子集)中的“总”点数,并在每一行上重复。获取百分比是一个简单的算术问题,您使用的表达式取决于数据类型,以及您希望如何格式化。

这里有一种方法(出几个可能的方式),以获得特定的结果:

SELECT t.id 
    , t.code 
    , t.points 
    -- , s.tot_points 
    , ROUND(t.points * 100.0/s.tot_points,1) AS percentage 
    FROM onetable t 
CROSS 
    JOIN (SELECT SUM(r.points) AS tot_points 
      FROM onetable r 
     ) s 
ORDER BY t.id 

查询s首先运行的观点,给人的单行。连接操作将该行与来自t的每一行进行匹配。这给了我们需要计算一个百分比的价值。

在不使用连接操作的情况下获得此结果的另一种方法是使用SELECT列表中的子查询返回总数。


请注意,可以扩展连接方法以获取每个“组”记录的百分比。

id type points %type 
-- ---- ------ ----- 
1 sold  11  22% 
2 sold   4  8% 
3 sold  25  50% 
4 bought  1 50% 
5 bought  1 50% 
6 sold  10  20% 

为了得到这一结果,我们可以使用相同的查询,但对于s AA视图查询,返回总GROUP BY r.type,然后加入操作是不是一个交叉连接,而是基于类型匹配:

SELECT t.id 
    , t.type 
    , t.points 
    -- , s.tot_points_by_type 
    , ROUND(t.points * 100.0/s.tot_points_by_type,1) AS `%type` 
    FROM onetable t 
    JOIN (SELECT r.type 
       , SUM(r.points) AS tot_points 
      FROM onetable r 
      GROUP BY r.type 
     ) s 
    ON s.type = t.type 
ORDER BY t.id 

要做到这一点相同的结果与子查询,这将是一个相关子查询,而查询是有可能得到t的每一行执行。

这就是为什么使用连接操作而不是SELECT列表中的子查询更自然,即使子查询的工作原理相同。 (我们用于更复杂查询的模式,比如为表分配别名,限定所有列引用以及格式化SQL ......这些模式只是回到简单的查询中,这些模式的原理有点简单。查询)

+0

有些无关的问题:数据库能够检测到子查询的结果是不变的,因此只评估一次? – 2014-10-01 12:27:12

+0

@Martin Thurau:是的,一个好的优化器应该认识到子查询可以运行一次,然后使用该常量。 (有效地将选择列表中的子查询转换为查询中指定的相同操作,但如果是相关的子查询,优化器不会这样做;假设您获得了不同类型的总点数(称为“买入”和“卖出“),并且你想要一个基于类型的百分比,很容易通过连接得到一个有效的计划;如果你在选择列表中使它成为一个相关的子查询,那么这个子查询将会被执行到每一行。 – spencer7593 2014-10-01 12:37:18

0

为了增加响应良好的名单,这应该是快速的性能,明智的,而且比较容易理解:

DECLARE @T TABLE (ID INT, code VARCHAR(256), Points INT) 

INSERT INTO @T VALUES (1,'101',2), (2,'201',3),(3,'233',4), (4,'123',1) 

;WITH CTE AS 
    (SELECT * FROM @T) 
SELECT C.*, CAST(ROUND((C.Points/B.TOTAL)*100, 2) AS DEC(32,2)) [%_of_TOTAL] 
FROM CTE C 
JOIN (SELECT CAST(SUM(Points) AS DEC(32,2)) TOTAL FROM CTE) B ON 1=1 

刚刚与CTE里面你实际的表替换表变量。

+1

我们应该注意到该语法不适用于其他数据库(例如Oracle,MySQL,Teradata等) – spencer7593 2014-10-01 12:48:34

+0

是的,真的,Darn,我为我的搜索标记了sql-server,但这只是SQL。:(但是,这个脚本确实是为SQL Server 2008及更高版本创建的。 – Kahn 2014-10-01 12:50:29