将每个部分中的一组数据和订单项分组,与T SQL中的其他部分分开

时间:2017-11-20 09:19:46

标签: sql-server tsql group-by sql-order-by

我有一组数据有2个字段“ActivationTime”,它是DATETIME&的类型。 “得分”是INT的类型。

我想根据这条规则对所有数据进行分组:

(1)每组中的数据必须相互间隔最多5天(对应于“ActivationTime”值。请注意,第一个“ActivationTime”是数据集中的最新“ActivationTime”。例如,在下面样品首先“ActivationTime”将是'2017-11-24 09:45:00.000',其得分= 1)

(2)分组数据的每个部分中的项目必须按“分数”值从“数据的其他分组部分”“单独”排序

如果有可能,有人可以帮助我吗?

编辑:例如想象@ExampleTabel如下:

Score                  ActivationTime
-------------------------------------------
  9               '2017-11-20 09:37:00.000'
  5               '2017-11-21 09:39:00.000'
  4               '2017-11-22 09:40:00.000'
  3               '2017-11-23 09:43:00.000'
  1               '2017-11-24 09:45:00.000'
  12              '2017-11-22 09:49:00.000'
  7               '2017-11-17 09:38:00.000'
  2               '2017-11-15 09:41:00.000'
  0               '2017-11-14 09:44:00.000'
  15              '2017-11-13 09:47:00.000'
  7               '2017-11-12 09:46:00.000'
  20              '2017-11-11 09:42:00.000'
  4               '2017-11-10 09:78:00.000'

除了生成之外的结果:

Score                 ActivationTime             Category
---------------------------------------------------------------
  12             '2017-11-20 09:49:00.000'          1
  9              '2017-11-20 09:37:00.000'          1
  5              '2017-11-21 09:39:00.000'          1
  4              '2017-11-22 09:40:00.000'          1
  3              '2017-11-23 09:43:00.000'          1
  1              '2017-11-24 09:45:00.000'          1

  15             '2017-11-13 09:47:00.000'          2
  7              '2017-11-17 09:38:00.000'          2
  2              '2017-11-15 09:41:00.000'          2
  0              '2017-11-14 09:44:00.000'          2

  20             '2017-11-11 09:42:00.000'          3
  7              '2017-11-12 09:46:00.000'          3
  3              '2017-11-20 09:37:57.570'          3
  4              '2017-11-10 09:78:00.000'          3

2 个答案:

答案 0 :(得分:1)

从你所说的话来看,你似乎想要这样的东西。

select
Score, ActivationTime, (rnk - 1) / 5 grp
from (
    select
        Score, ActivationTime, dense_rank()over(order by cast(ActivationTime as date) desc) rnk
from
    mytable
) t
order by grp, Score desc

您应该提供一些示例数据以及您希望获得更好帮助的结果

答案 1 :(得分:0)

根据您的评论,这是您在N Days返回时的方式。

首先,我创建一个虚拟表,其中包含我想要返回多少天的数字。这个表然后在我的光标中循环以创建我的CTE语句。最后我联合我所有的CTE,然后通过激活时间和分数来订购

/*SCRIPT */

DECLARE @NDaysAgo nvarchar(2) = 20 --Change this based on how many days you want to go back
DECLARE @Number nvarchar(2)
DECLARE @sqlCreateNumbers nvarchar(max)
DECLARE @AliasName nvarchar(50)
DECLARE @SQL nvarchar(max)
DECLARE @SQLUnion nvarchar(max)
 DECLARE @crlf nvarchar(max)
 SET @crlf = CHAR(13)
DECLARE @SQLTotal nvarchar(MAX)

Set @sqlCreateNumbers = '

IF EXISTS (SELECT * FROM sys.objects 
WHERE object_id = OBJECT_ID(N''[dbo].[numbers]'') AND type in (N''U''))
DROP TABLE [dbo].[numbers];

SELECT TOP '+@NDaysAgo+' IDENTITY(int,0,1) AS n 
into dbo.numbers
FROM MASTER..spt_values a, MASTER..spt_values b;

CREATE UNIQUE CLUSTERED INDEX idx_1 ON numbers(n);


'
PRINT @sqlCreateNumbers

EXEC (@sqlCreateNumbers)


DECLARE SqlCur CURSOR FOR
Select DaysAgo = N,Alias = 'Today'+cast(N as nvarchar(50))
from dbo.Numbers
OPEN SqlCur
FETCH NEXT FROM SqlCur
INTO @Number,@AliasName
IF (@@FETCH_STATUS>=0)
BEGIN
SET @SQL = 'with '+@AliasName+' as (
Select '''+@AliasName+''' as SourceName,Score,ActivationTime
from dbo.testactivation
Where cast(ActivationTime as date) = cast(dateadd(dd,'+@Number+',GETDATE()) as date)

)'

SET @SQLUnion = 'Select * from '+@AliasName+''

--PRINT @SQL
FETCH NEXT FROM SqlCur INTO @Number,@AliasName
 END
 WHILE (@@FETCH_STATUS<>-1)

 BEGIN
 IF (@@FETCH_STATUS<>-2)

 SET @SQL = @SQL + ','+@AliasName+' as (
Select '''+@AliasName+''' as SourceName,Score,ActivationTime
from dbo.testactivation
Where cast(ActivationTime as date) = cast(dateadd(dd,-'+@Number+',GETDATE()) as date)

)'
SET @SQLUnion =  @SQLUnion + @crlf+ ' union all Select * from '+@AliasName+''
--PRINT @SQL

FETCH NEXT FROM SqlCur INTO @Number,@AliasName
END

 CLOSE SqlCur
 DEALLOCATE SqlCur


SET @SQLTotal = @SQL + 'Select * from ( '+@SQLUnion+ ' ) x ORDER BY ACTIVATIONTIME DESC, SCORE DESC'

PRINT @SQLTotal --This will not show you all records since there is a limit to how much text it can show
Select @SQLTotal -- If you select it you can see the query

EXEC(@SQLTotal) --This will execute your statement, so you can see your descired result

修改 如果您无法使用变量而无法获得NDays,那么您必须对其进行硬编码。

使用一个查询

Select 'Data' as SourceName,Score,ActivationTime
from dbo.testactivation
Where cast(ActivationTime as date) between cast(dateadd(dd,0,GETDATE()) as date)
and cast(dateadd(dd,-20,GETDATE()) as date)
order by ActivationTime desc,score desc

<强>结果 enter image description here