2014-11-06 39 views
1

请大家关注我们数据库的当前结构。计算从一种状态到另一种状态所花费的时间:SQL

enter image description here

我们的DBA是目前远在接下来的两个星期,我有非常有限的SQL知识,我想留在UI和中间层。

我们想要弄清楚的是我们如何做到以下几点,我们需要编写一个查询来计算所有佣金已经从“已验证”过渡到“已付费”的平均时间段(天)单一的经销商,目前的状态是

  1. 创建
  2. 验证
  3. 拒绝
  4. 等待付款
  5. 付费
  6. Refined

我认为这个查询需要直接针对委员会历史表?

我不知道我怎么会去写这样的查询由于我的SQL知识是有限的......

任何帮助将是巨大的。

+1

在可复制,与你想的输出应沿着格式添加一堆样本数据(比如10-15行) 。此外,事实可以退还的事实影响你想在你的输出中显示的东西,因为这将不再支付? – Tanner 2014-11-06 09:55:18

+0

您的状态1-6是否在'NewPaymentStatusId'中保存? – Tanner 2014-11-06 10:03:03

+0

@Tanner如果已经退款了,那么是状态为1-6,理想情况下我们不会担心,我们将在某个时间点延长此日期范围。 – 2014-11-06 10:06:29

回答

0

对于历史表中的每个佣金,您都可以获得最长验证日期和最短支付日期,假定支付日期始终晚于验证日期。然后你可以加入佣金表,按经销商ID分组,得到平均持续时间,以天为单位。

with comm as(
select 
    commissionid, 
    max(case NewPamentStatus when 'Verified' then ActionDate else null end) as verified_date, 
    min(case NewPamentStatus when 'Paid' then ActionDate else null end) as paid_date 
     --using max or min just incase that same status will be recorded more than one time. 
from 
    CommissionHistory 
group by 
    commistionid 
) 
select 
    c.DealerId, 
    avg(datediff(day,comm.verified_date,comm.paid_date)) 
from 
    comm 
inner join 
    commission c 
on c.commissionid = comm.commissionid 
where 
    datediff(day,comm.verified_date,comm.paid_date)>0 
    -- to get rid off the commissions with paid date before the verified date or in same day 
group by 
    c.DealerId 
0

这里实现你以后的方法,虽然它可能不是最有效的。在我看来,这更像是你正在运行的一次性查询,而不是你要频繁运行以影响数据库性能的事情。

测试表设定:

CREATE TABLE Commission 
(
    CommissionId INT, 
    DealerId INT 
) 

CREATE TABLE CommissionHistory 
(
    CommissionId INT, 
    ActionDate DATETIME, 
    NewPaymentStatusId INT 
) 

插入伪数据 - 5个委员会1个经销商:

INSERT INTO dbo.Commission 
     (CommissionId , 
      DealerId 
     ) 
VALUES (1 , 1), 
     (2 , 1), 
     (3 , 1), 
     (4 , 1), 
     (5 , 1), 

INSERT INTO dbo.CommissionHistory 
     (CommissionId , 
      ActionDate , 
      NewPaymentStatusId 
     ) 
VALUES (1 , GETDATE() -25, 1), 
     (1 , GETDATE() -21, 2), 
     (1 , GETDATE() -18, 3), 
     (1 , GETDATE() -16, 4), 
     (1 , GETDATE() -5, 5), 
     (2 , GETDATE() -10, 1), 
     (2 , GETDATE() -9, 2), 
     (2 , GETDATE() -8, 3), 
     (2 , GETDATE() -7, 4), 
     (2 , GETDATE() -6, 5), 
     (3 , GETDATE() -10, 1), 
     (3 , GETDATE() -8, 2), 
     (3 , GETDATE() -6, 3), 
     (3 , GETDATE() -4, 4), 
     (3 , GETDATE() -2, 5), 
     (3 , GETDATE() -25, 6), 
     (4 , GETDATE() -10, 1), 
     (4 , GETDATE() -7, 2), 
     (4 , GETDATE() -6, 3), 
     (4 , GETDATE() -4, 4), 
     (4 , GETDATE() -1, 5), 
     (5 , GETDATE() -1, 1), 
     (5 , GETDATE() -1, 2) 

因此,与伪数据,委员会1,2 &,4是归类为有效记录,因为它们具有状态2和5.因为它被退还,所以被排除在外,因为它没有被支付,所以被排除。

要生成我写了下面的查询平均值:

-- set the required dealer id 
DECLARE @DealerId INT = 1 

-- return all CommissionId's in to a temp table that have statuses 2 and 5, but not 6 
SELECT DISTINCT CommissionId 
INTO #DealerCommissions 
FROM dbo.CommissionHistory t1  
WHERE CommissionId IN (SELECT CommissionId 
         FROM dbo.Commission 
         WHERE DealerId = @DealerId) 
AND NOT EXISTS (SELECT CommissionId 
       FROM dbo.CommissionHistory t2 
       WHERE t2.NewPaymentStatusId = 6 AND t2.CommissionId = t1.CommissionId) 
AND EXISTS (SELECT CommissionId 
      FROM dbo.CommissionHistory t2 
      WHERE t2.NewPaymentStatusId = 2 AND t2.CommissionId = t1.CommissionId) 
AND EXISTS (SELECT CommissionId 
      FROM dbo.CommissionHistory t2 
      WHERE t2.NewPaymentStatusId = 5 AND t2.CommissionId = t1.CommissionId) 

-- use the temp table to return average difference between the MIN & MAX date 
;WITH cte AS (
    SELECT CommissionId FROM #DealerCommissions 
) 
SELECT AVG(CAST(DaysToCompletion AS DECIMAL(10,8))) 
FROM (
     SELECT DATEDIFF(DAY, MIN(ch.ActionDate), MAX(ch.ActionDate)) DaysToCompletion 
     FROM cte 
     INNER JOIN dbo.CommissionHistory ch ON ch.CommissionId = cte.CommissionId 
     GROUP BY ch.CommissionId 
) AS averageDays 

-- remove temp table 
DROP TABLE #DealerCommissions 
相关问题