Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.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 server 2008 r2 统计按日期范围划分的值以前出现的次数_Sql Server 2008 R2_Analytic Functions - Fatal编程技术网

Sql server 2008 r2 统计按日期范围划分的值以前出现的次数

Sql server 2008 r2 统计按日期范围划分的值以前出现的次数,sql-server-2008-r2,analytic-functions,Sql Server 2008 R2,Analytic Functions,这里有一个简单的查询,我们可以根据过去90天内收到的销售线索,从我们的营销部门获得临时请求 SELECT ID ,FIRST_NAME ,LAST_NAME ,ADDRESS_1 ,ADDRESS_2 ,CITY ,STATE ,ZIP ,HOME_PHONE ,MOBILE_PHONE ,EMAIL_ADDRESS ,ROW_ADDED_DTM FROM WEB_LEADS WHERE ROW_ADDED_

这里有一个简单的查询,我们可以根据过去90天内收到的销售线索,从我们的营销部门获得临时请求

SELECT ID
    ,FIRST_NAME
    ,LAST_NAME
    ,ADDRESS_1
    ,ADDRESS_2
    ,CITY
    ,STATE
    ,ZIP
    ,HOME_PHONE
    ,MOBILE_PHONE
    ,EMAIL_ADDRESS
    ,ROW_ADDED_DTM
FROM WEB_LEADS
WHERE ROW_ADDED_DTM BETWEEN @START AND @END
他们要求添加更多派生列,以显示电子邮件地址匹配的地址1之前出现的次数。但他们想要的是不同的日期范围

因此,派生列将如下所示:

,COUNT_ADDRESS_1_LAST_1_DAYS,
,COUNT_ADDRESS_1_LAST_7_DAYS
,COUNT_ADDRESS_1_LAST_14_DAYS
etc.

我已经使用update语句手动填充了这些派生列,当时只有几个。上面的查询实际上只是一个包含更多列的更大查询的示例。实际请求已扩展到13列的6个日期范围。我想问的是,是否有比使用78条额外的更新语句更好的方法。

我认为,如果不实际创建一个对不同选择进行硬编码的查询,您将很难编写一个包含每个电子邮件地址的所有这78条指标的查询。但是,您可以使用动态SQL生成这样的pivot查询,这将为您节省一些击键次数,并在向表中添加更多列时进行动态调整

您希望得到的结果将如下所示(但您当然不想键入):

这有点复杂,它应该作为一个脚本运行,但我将把它分成几块,在不键入它们的情况下散布关于如何填充上述部分的注释。(不久,@Bluefeet可能会有一个更好的PIVOT替代方案。)我将把我散布的注释放在
/*
*/
中,这样您仍然可以将大部分答案复制到Management Studio中,并完整地运行它

要复制的代码/注释如下:


/* 首先,让我们构建一个日期表,它既可以用于派生用于数据透视的标签,也可以用于辅助聚合。我已经添加了您提到的三个范围,并猜测了第四个范围,但希望能够清楚地知道如何添加更多: */

/* 接下来,让我们构建每个列名重复的查询部分。首先,聚合部分的格式是
col=COUNT(DISTINCT col)
。我们将转到目录视图,动态地导出列名列表(除了
ID
EMAIL\u ADDRESS
ROW\u ADDED\u DTM
)并将它们填充到一个临时表中以供重用。 */

/* 接下来,我们将构建“pivot”部分(尽管我正在寻找穷人的pivot-一组
CASE
表达式)。对于每个列名,我们需要针对每个范围设置一个条件,因此我们可以通过将列名列表与标签表交叉连接来实现这一点。(我们将在稍后的查询中再次使用这一精确的技术,使过去6个日期中的一个*/部分起作用。 */

/* 现在,根据需要填充这两部分,我们可以构建一个动态SQL语句来填充其余部分: */

/* 现在再说一遍,这是一段相当复杂的代码,也许使用
PIVOT
可以让它变得更简单。但我认为即使@Bluefeet也会编写一个使用动态SQL的
PIVOT
,因为这里的硬代码太多了。
*/

很难满足这些要求。对于系统中每个唯一的电子邮件地址,他们需要一个在过去一天、7天、14天等时间段内拥有的不同地址值的计数,以及在这些时间段内拥有的不同地址值的计数。还有城市值、州值和邮政区号值等。而你不需要我不想重复列名或日期范围(我想你不是指“更新声明”)?大家好,很抱歉耽误了回来。我得了流感,几天后就会回来。
;WITH y AS
(
  SELECT 
    EMAIL_ADDRESS,

/* aggregation portion */

    [ADDRESS_1] = COUNT(DISTINCT [ADDRESS_1]),
    [ADDRESS_2] = COUNT(DISTINCT [ADDRESS_2]),
    ... other columns

/* end agg portion */

    FROM dbo.WEB_LEADS AS wl 
    WHERE ROW_ADDED_DTM >= /* one of 6 past dates */
    GROUP BY wl.EMAIL_ADDRESS
)
SELECT EMAIL_ADDRESS,

/* pivot portion */

  COUNT_ADDRESS_1_LAST_1_DAYS = *count address 1 from 1 day ago*,
  COUNT_ADDRESS_1_LAST_7_DAYS = *count address 1 from 7 days ago*,
  ... other date ranges ...
  COUNT_ADDRESS_2_LAST_1_DAYS = *count address 2 from 1 day ago*,
  COUNT_ADDRESS_2_LAST_7_DAYS = *count address 2 from 7 days ago*,
  ... other date ranges ...
  ... repeat for 11 more columns ...

/* end pivot portion */
FROM y 
GROUP BY EMAIL_ADDRESS
ORDER BY EMAIL_ADDRESS;
DECLARE @d DATE = SYSDATETIME();

CREATE TABLE #L(label NVARCHAR(15), d DATE);

INSERT #L(label, d) VALUES
(N'LAST_1_DAYS',  DATEADD(DAY,   -1,  @d)),
(N'LAST_7_DAYS',  DATEADD(DAY,   -8,  @d)),
(N'LAST_14_DAYS', DATEADD(DAY,   -15, @d)),
(N'LAST_MONTH',   DATEADD(MONTH, -1,  @d));
SELECT name INTO #N FROM sys.columns
WHERE [object_id] = OBJECT_ID(N'dbo.WEB_LEADS')
AND name NOT IN (N'ID', N'EMAIL_ADDRESS', N'ROW_ADDED_DTM');

DECLARE @agg NVARCHAR(MAX) = N'', @piv NVARCHAR(MAX) = N'';

SELECT @agg += ',
  ' + QUOTENAME(name) + ' = COUNT(DISTINCT ' 
  + QUOTENAME(name) + ')' FROM #N;

PRINT @agg;
SELECT @piv += ',
  COUNT_' + n.name + '_' + l.label
  + ' = MAX(CASE WHEN label = N''' + l.label 
  + ''' THEN ' + QUOTENAME(n.name) + ' END)'
FROM #N as n CROSS JOIN #L AS l;

PRINT @piv;
DECLARE @sql NVARCHAR(MAX) = N';WITH y AS
(
    SELECT 
      EMAIL_ADDRESS, l.label' + @agg + '
      FROM dbo.WEB_LEADS AS wl 
      CROSS JOIN #L AS l
      WHERE wl.ROW_ADDED_DTM >= l.d
      GROUP BY wl.EMAIL_ADDRESS, l.label
)
SELECT EMAIL_ADDRESS' + @piv + '
FROM y 
GROUP BY EMAIL_ADDRESS
ORDER BY EMAIL_ADDRESS;';

PRINT @sql;

EXEC sp_executesql @sql;
GO
DROP TABLE #N, #L;