Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于计算中值和分组依据的SQL查询_Sql_Sql Server 2008_Tsql - Fatal编程技术网

用于计算中值和分组依据的SQL查询

用于计算中值和分组依据的SQL查询,sql,sql-server-2008,tsql,Sql,Sql Server 2008,Tsql,我有下表 DECLARE @TBL_RESULT Table ( ID varchar(10), CreateDate DateTime, PEOPLE_CODE_ID varchar(10), CONVERSION_DATE DateTime, CAMPUS varchar(20), DAYS_TOOK int ); 此表记录了从2013年1月1日到目前为止接收和转换的所有潜在客户 最初,我需要找到转换过去10周内到达的潜在客户并

我有下表

DECLARE @TBL_RESULT Table
(   
    ID varchar(10),
    CreateDate DateTime,
    PEOPLE_CODE_ID varchar(10), 
    CONVERSION_DATE DateTime,
    CAMPUS varchar(20),
    DAYS_TOOK int   
);
此表记录了从2013年1月1日到目前为止接收和转换的所有潜在客户

最初,我需要找到转换过去10周内到达的潜在客户并按校园分组所需的中间时间。我可以使用下面的SQL查询来完成这项工作

WITH    CTE_RESULT
          AS ( SELECT   *
               FROM     @TBL_RESULT
               WHERE    CreateDate > DATEADD(WEEK, -10, GETDATE())
             )
    SELECT  Campus ,
            AVG(DAYS_TOOK) AS MedianTime
    FROM    ( SELECT    CAMPUS ,
                        Days_Took ,
                        ROW_NUMBER() OVER ( PARTITION BY Campus ORDER BY Days_Took ASC ) AS AgeRank ,
                        COUNT(*) OVER ( PARTITION BY CAMPUS ) AS CampusCount
              FROM      CTE_RESULT
            ) x
    WHERE   x.AgeRank IN ( x.CampusCount / 2 + 1, ( x.CampusCount + 1 ) / 2 )
    GROUP BY x.Campus   
我现在需要在图表上绘制这一趋势,即查找前10周的记录,并在折线图上绘制中值,其中每条线为一个校园。按校园分组

光标是我唯一的选择吗?在这里,我将查找从1月1日开始的前10周的潜在客户,执行上面的SQL查询以获得中间值,将其推送到临时表,然后查找接下来的10周,依此类推


还是我能做得更好?

看来你解决了问题的难点

为了得到您想要的,您需要引入一个分组变量。在本例中,我测量过去的周数,然后除以10,SQL Server会进行整数除法,因此生成一个整数

然后在partitionby和groupby语句中明智地使用它:

WITH CTE_RESULT AS (
       SELECT   t.*,
                DATEDIFF(week, CreateDate, GETDATE()) / 10 as groupnum
       FROM     @TBL_RESULT t
      )
SELECT Campus, groupnum, MIN(CreateDate), MAX(CreateDate),
       AVG(DAYS_TOOK) AS MedianTime
FROM (SELECT t.*,
              ROW_NUMBER() OVER (PARTITION BY groupnum, Campus ORDER BY Days_Took ASC ) AS AgeRank ,
              COUNT(*) OVER (PARTITION BY groupnum, CAMPUS) AS CampusCount
      FROM CTE_RESULT t
     ) x
WHERE x.AgeRank IN ( x.CampusCount / 2 + 1, ( x.CampusCount + 1 ) / 2 )
GROUP BY x.Campus, groupnum

我还没有对此进行测试,因此它可能有一两个语法错误。

在不优化查询的情况下,如果您需要在多个10周期间生成相同的结果,您可以根据需要将当前10周前到今天的范围扩展到任意多个范围,在整个查询中使用PeriodEndDate,如下所示

MS SQL Server 2012架构设置:

问题1:


不,这不需要光标。你能澄清你所说的“周”是什么意思吗?你是从1月1日开始,然后69天后就是10周的结束时间吗?或者周是由ISO周定义的?或者由脚本向后运行的日期定义?最初,当我编写查询时,我只需要最后10周的时间,所以我根据脚本运行的日期向后运行了10周。例如,如果脚本在4/18运行,则开始日期为02/07。@user1828125。如果你对我的答案投了反对票,为什么?实际上我没有——我按下了“向上”按钮,只是仔细检查了一下ಠ_ಠ 认真地你要买inb4徽章吗?@swasheckԾԾԾ相当奇怪至少底部的派生表中缺少groupnum。如果一个查询足够复杂,对新手来说就像魔术一样,那么一两个语法错误就越来越不可能被OP修复,答案的值也会急剧下降。@RichardTheKiwi。答案是针对提问者的。他/她似乎对SQL非常精通。我认为我在解释解决问题的方法方面做得相当好。SQL就是一个例子。@user1828125。理查德:谢谢你的回复,但我认为这并没有给我10周加起来的中位数。我预计在整个10周内,每个校园都会有一排学生。每个校园每周都没有一排。我从你的查询中得到的结果实际上是每周每个校园的中位数。结果是每10周每个校园一行。每个数据点是一个校园/10周期间的中位数,这是您最初拥有的。例如,如果说今天结束的校园A时段中位数为100,则意味着今天结束的校园A的10周时段中位数为100。Richard-您建议的解决方案实际上是将中位数移动一周,然后计算10周。很抱歉,我原来的问题没有澄清这一点。但我实际上也要做另一份关于移动中间值的报告,所以你们实际上已经回答了我的第二个问题。再次感谢你!
DECLARE @TBL_RESULT Table
(   
    ID varchar(10),
    CreateDate DateTime,
    PEOPLE_CODE_ID varchar(10), 
    CONVERSION_DATE DateTime,
    CAMPUS varchar(20),
    DAYS_TOOK int   
);

-- fill the table with some dummy data from 2013-01-01
INSERT @TBL_RESULT (CreateDate, Campus, Days_Took)
SELECT DATEADD(D, A.Number, '20130101'), 'Campus' + Right(B.Number, 10),
       ABS(CAST(NEWID() AS binary(6)) % 130) + 1
FROM master..spt_values A
JOIN master..spt_values B on B.type='P' and B.number < 50 -- 50 campuses
WHERE A.type='P'
  AND DATEADD(D, A.Number, '20130101') <= GetDate();

-- This first CTE is used to create the required number of 10-week periods
WITH N(NUMBER) AS (
  SELECT 0
  union all
  select number+1 from N
  where Number <= DATEDIFF(WEEK, '20130101', GETDATE())
),
-- and from below here it's your query with the PeriodEndDate threaded through
CTE_RESULT AS (
  SELECT   DATEADD(WEEK, -Number, GETDATE()) PeriodEndDate,
           T.*
  FROM     @TBL_RESULT T
  CROSS    JOIN     N
           -- you see the range built up dynamically here
  WHERE    CreateDate > DATEADD(WEEK, -Number-10, GETDATE())
    AND    CreateDate < DATEADD(WEEK, -Number, GETDATE()) +1
)
SELECT  PeriodEndDate, Campus ,
        AVG(DAYS_TOOK) AS MedianTime
FROM    (
         SELECT PeriodEndDate,   CAMPUS ,
         Days_Took ,
         ROW_NUMBER() OVER ( PARTITION BY PeriodEndDate, Campus ORDER BY Days_Took ASC ) AS AgeRank ,
         COUNT(*) OVER ( PARTITION BY PeriodEndDate, CAMPUS ) AS CampusCount
         FROM      CTE_RESULT
        ) x
WHERE   x.AgeRank IN ( x.CampusCount / 2 + 1, ( x.CampusCount + 1 ) / 2 )
GROUP BY x.PeriodEndDate, x.Campus
ORDER BY x.PeriodEndDate, x.Campus;