每组[日期]删除随机记录[0-4个删除]

Delete random records [0-4 deletions] per group [date]

我需要为演示文稿创建虚拟数据。

我得到了 10 条记录,我需要复制它们并在每个月的每一天每次更改它们的日期。然后我需要删除每个日期的随机记录,每天从 0 到 4 条记录不等(因此它们看起来更随机)

一个简化的例子

dummyId Name  onDate
1       xd    2016-07-01
2       gd    2016-07-01
3       yd    2016-07-01
4       ad    2016-07-01
5       bd    2016-07-01
6       zd    2016-07-01
7       md    2016-07-01
8       qd    2016-07-01
9       nd    2016-07-01
10      dd    2016-07-01
11       xd    2016-07-02
12       gd    2016-07-02
13       yd    2016-07-02
14       ad    2016-07-02
15       bd    2016-07-02
16       zd    2016-07-02
17       md    2016-07-02
18       qd    2016-07-02
19       nd    2016-07-02
20       dd    2016-07-02

..

在上面的例子中,7 月 1 日的记录被复制到 7 月 2 日。这将持续到每个七月的日期。之后,我需要从每组日期中删除 [7 月 1 日除外](按日期分组)0-4 条记录,以便数据看起来是随机的。

例如,7 月 2 日删除了以下 3 条记录

dummyId    Name  onDate
    1       xd    2016-07-01
    2       gd    2016-07-01
    3       yd    2016-07-01
    4       ad    2016-07-01
    5       bd    2016-07-01
    6       zd    2016-07-01
    7       md    2016-07-01
    8       qd    2016-07-01
    9       nd    2016-07-01
    10      dd    2016-07-01
    11       xd    2016-07-02
    13       yd    2016-07-02
    14       ad    2016-07-02
    16       zd    2016-07-02
    17       md    2016-07-02
    18       qd    2016-07-02
    20       dd    2016-07-02
.. 

如果需要删除0-4条记录,可以使用随机数。这很痛苦,但在 SQL 服务器中你可以这样做:

delete s
    from simplified s
    where onDate <> '2016-07-01' and
          rand(checksum(newid())) < 0.15;

这将删除大约 15% 的记录。这应该是每个日期的 1-4 条记录(尽管不能保证每个日期的确切数量)。

为每个日期删除固定数字的另一种方法是。例如,return 每个日期的三个记录:

with todelete as (
      select s.*, row_number() over (partition by date order by newid()) as seqnum
      from simplified s
     )
delete todelete
    where seqnum <= 3 and onDate <> '2016-07-01';

一种方法是为每个日期的记录创建一个 cte that will generate a random number for each record and a row number 随机排序:

创建并填充样本 table(请在下一个问题中省去这一步):

DECLARE @T as table
(
    dummyId int,
    Name char(2),
    onDate date
)

INSERT INTO @T VALUES
(1, 'xd', '2016-07-01'),
(2, 'gd', '2016-07-01'),
(3, 'yd', '2016-07-01'),
(4, 'ad', '2016-07-01'),
(5, 'bd', '2016-07-01'),
(6, 'zd', '2016-07-01'),
(7, 'md', '2016-07-01'),
(8, 'qd', '2016-07-01'),
(9, 'nd', '2016-07-01'),
(10, 'dd', '2016-07-01'),
(11, 'xd', '2016-07-02'),
(12, 'gd', '2016-07-02'),
(13, 'yd', '2016-07-02'),
(14, 'ad', '2016-07-02'),
(15, 'bd', '2016-07-02'),
(16, 'zd', '2016-07-02'),
(17, 'md', '2016-07-02'),
(18, 'qd', '2016-07-02'),
(19, 'nd', '2016-07-02'),
(20, 'dd', '2016-07-02')

创建一个cte。请注意,它包含一个介于 0 到 5(含)之间的随机数,以及每个日期的 1 到 10 之间的行号,随机排序:

;WITH CTE AS
(
    SELECT  dummyId, 
            Name, 
            onDate, 
            ABS(CHECKSUM(NEWID()) % 6) as random,
            ROW_NUMBER() OVER(PARTITION BY onDate ORDER BY NEWID()) As rowNumber
    FROM @T 
    WHERE onDate <> '2016-07-01'
)

从cte中删除。请注意,where 子句正在检查随机数是否小于行号。 where 子句确保对于每个日期,将删除随机数的 0 到 4 条记录:

DELETE
FROM CTE
WHERE rowNumber < random