2014-10-01 3 views
4

Привет, как я могу получить процент каждой записи над общей суммой? Представим У меня есть одна таблица со следующейПроценты/Процент процента от всех

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

Процент для ID 1 является 20% для 2 является 30% и поэтому один как я получаю это?

+2

Какая СУБД вы используете? – DirkNM

ответ

1

попробовать, как этот

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

Совершенно работает Спасибо – Joaquim

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, который возвращает общее 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

Совсем не связанный вопрос: может ли база данных обнаруживать, что результат подзадача является постоянным и поэтому оценивает его только один раз? –

+0

@Martin Thurau: Да, хороший оптимизатор должен признать, что подзапрос можно запустить один раз, а затем использовать эту константу. (Эффективное преобразование подзапроса в списке выбора в ту же самую операцию, указанную в моем запросе. Но оптимизатор не сделает этого, если это коррелированный подзапрос, скажем, вы получали общие точки разных типов (например, «купили» и «продали» «), и вам нужен процент, основанный на типе. Легко получить эффективный план с соединением, если вы сделаете его коррелированным подзапросом в списке выбора, тогда этот подзапрос будет выполнен для каждой строки. – spencer7593

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 

Просто замените переменные таблицы с фактической таблицей внутри КТРА.

+1

Следует отметить что этот синтаксис для SQL Server.Этот синтаксис не будет работать в других базах данных (например, Oracle, MySQL, Teradata и др.) – spencer7593

+0

Да, правда. Darn, я пометил sql-сервер для моего поиска, но это просто sql. :(Но да, этот сценарий действительно создан только для SQL Server 2008 и более поздних версий. – Kahn

Смежные вопросы