Как рассчитать процент - PullRequest
2 голосов
/ 05 марта 2012

Table1

Date     id   salary

01/2012  001   1500
01/2011  001   750
01/2010  001   500

из таблицы1, я хочу сделать процент для даты

Ожидаемый результат

Date    id  salary percentage

01/2012 001 1500   100%
01/2011 001 750    50% 
01/2010 001 500    0%

Условие

01/2010 salary is 500, then 01/2011 salary is 750, so 50 percentage increased from 01/2010 salary
01/2011 salary is 750, then 01/2012 salary is 1500, so 100 percentage increase from 02/2011 salary

Как сделать запрос для расчета процента.

Нужна помощь в запросе

Ответы [ 6 ]

3 голосов
/ 05 марта 2012

Как сказал @richardtallent, есть две части: (1) поиск предыдущей зарплаты и (2) расчет процента. Но так как вы используете sqlserver, 2k CTE не поддерживаются. Я использую, чтобы сделать следующим образом:

Для (2) у меня обычно создаются две функции: процент и приращение:

CREATE FUNCTION [dbo].[percentage] (@a float(53), @b float(53))
RETURNS float(53)
BEGIN
  RETURN (CASE WHEN COALESCE(@b,0)=0 THEN NULL ELSE @a/@b END)*100.
END

И

CREATE FUNCTION [dbo].[increment] (@a float(53), @b float(53))
RETURNS float(53)
BEGIN
  RETURN dbo.percentage(@a,@b)-100.
END

Для (1) вы можете использовать подвыбор, а затем он у вас есть.

SELECT S.date, S.id, S.salary, 
       dbo.increment((SELECT TOP 1 salary 
                      FROM table1 
                      WHERE id=S.id AND date<S.date 
                      ORDER BY date DESC),
                     salary) AS percentage
FROM table1 S
0 голосов
/ 05 марта 2012

Попробуйте: это более динамично:

create table #tr(dates datetime,id int,salary int)
insert into #tr values('01/01/2012' , 001 ,  1500)
insert into #tr values('01/01/2011'  ,001,   750)
insert into #tr values('01/01/2010' , 001 ,  500)
insert into #tr values('01/01/2011'  ,002,   750)
insert into #tr values('01/01/2010' , 002 ,  500)

with T as (
select ID, dates incDate, Salary, ROW_NUMBER() over( partition by id order by id, Dates) AS rn from #tr)
select T.id,T1.salary ,T.incdate,(T1.Salary-T.salary)*100/T.Salary as PercHike  from T join T T1 on T.id=T1.id and T.rn=(T1.rn-1)
UNION
select id,min(Salary) as Salary ,min(dates) as Incdate , 0 as PercHike from #tr group by Id 
ORDER BY ID , incDate

drop table #tr

В сценарии, где Id отличаются, ранее предложенное решение выполняет.

0 голосов
/ 05 марта 2012

Попробуйте это

create table #tr(dates datetime,id int,salary int)
insert into #tr values('01/01/2012' , 001 ,  1500)
insert into #tr values('01/01/2011'  ,001,   750)
insert into #tr values('01/01/2010' , 001 ,  500);

WITH tablename as
(

SELECT ROW_NUMBER()over(PARTITION by t1.dates  order by t1.dates)rno, T1.*,isnull((cast((T1.salary - isnull(T2.salary,T1.salary))as decimal(16,3))/T2.salary),0)*100 as 'Percentage'  FROM #tr T1
left JOIN #tr T2 on T1.id = T2.ID and T1.dates >T2.dates 

)  

SELECT * FROM tablename where rno = 1    

drop table #tr
0 голосов
/ 05 марта 2012

Вы можете сделать это с помощью CTE, выполнив что-то вроде:

WITH CTETable (Row, Date, id, salary) AS
(
    SELECT Row_Number() over (order by id,Date) AS Row , 
    Date,
         id, 
    salary
    FROM sourceTable
) 
SELECT 
    T1.Row, 
    T1.Date,
         T1.id
    T1.salary, 
    CASE 
                  -- First row in table, return 0 for Pct
        WHEN T1.Row = 1 THEN 0
                  -- Switching ids, return 0 for Pct
                  WHEN T1.id <> (SELECT T2.id FROM CTETable AS T2
                                 WHERE T2.Row = T1.Row - 1) THEN 0
                  -- else subtract the prior row's salary from the current row
                  -- and divide by the prior row's salary
        ELSE (T1.salary - (SELECT T2.salary FROM CTETable AS T2 
                WHERE T2.Row = T1.Row - 1) * 1.0)  /
             ((SELECT T3.salary FROM CTETable AS T3 
              WHERE T3.Row = T1.Row - 1) * 1.0)
    END * 100 AS Pct
FROM CTETable AS T1
0 голосов
/ 05 марта 2012

В моем View Better вы выбираете курсоры, сначала создайте столбец, изменив таблицу, и извлеките последнюю строку с помощью курсора в таблице

declare @date datetime,@id int,@salary numeric,@percentage decimal(5,2)
declare SalCursor cursor static
  FOR SELECT date,id,Salary FROM table1
  open SalCursor 
  fetch last FROM SalCursor into @date,@id,@salary
  while @@fetch_status<>-1
  begin
    --code to calculate  percentage goes here
  Update table1 set percentage=@percentage where id=@id
  end

Надеюсь, это даст вам грубую идею ... Всего наилучшего ..

0 голосов
/ 05 марта 2012

Этот вопрос состоит из двух частей: (1) найти предыдущую зарплату для любой заданной зарплаты и (2) рассчитать процент.

Первая часть:

WITH salarieswithprevious AS (
   SELECT date, id, salary, 
      COALESCE(SELECT salary FROM table t2 WHERE t1.id=t2.id AND t1.date > t2.date
         AND NOT EXISTS(SELECT NULL FROM table t3 WHERE t3.id=t1.id 
            AND t3.date > t2.date AND t3.date < t1.date), salary) AS previoussalary
   FROM
      table t1
   )

Это соответствует каждой зарплате с самой последней зарплатой до нее. Это объединяет значение с текущей зарплатой, если нет предыдущей зарплаты, что означает, что «повышение» за этот год будет 0%.

Вторая часть:

SELECT date, id, salary, 
   ( (salary - previoussalary) / previoussalary * 100 ) AS PctIncrease
FROM
   salarieswithprevious

Это делает легкую часть, простой процент математики.

...