SQL Server计算值在多个日期范围之间出现的次数

时间:2017-08-14 16:52:38

标签: sql-server tsql sql-server-2012 sql-server-2014

我有一个有两列问题的表格。

  • A栏 - 时间戳
  • B栏 - EmpID

我要做的是比较几周,看看EmpID重复了多少次。例如:

第1周是我的基础(开始日期范围,例如BETWEEN' 2017-07-22' AND' 2017-07-29 23:59:59.993')。我现在想比较第2周和第1周。如果EmpID在第2周重复,我会看到2的计数,如果它在第2周第一次出现,那么计数为1.

继续第3周。如果EmpID出现在第1周,第2周和第3周,那么我想看到3的计数,如果它只出现在第2周和第3周然后计数为2,如果它只出现在第3周那么计数为1.

最后是第4周。如果EmpID出现在第1周,第2周,第3周和第4周,那么我希望看到计数为4.如果EmpID出现在第2周,第3周和第4周,则计数为3,如果它出现在第3周和第4周,则计数为2如果它仅在第4周出现,则计数为1.

非常感谢任何帮助。

添加了我迄今为止尝试但未获得预期效果的内容。

select t.emp_id,
(select count(emp_id) 
from [Vacation Audit Care 2017]
WHERE ((UPLOAD_DATE BETWEEN '2017-07-22' AND '2017-07-29 23:59:59.993') or(UPLOAD_DATE BETWEEN '2017-07-29' AND '2017-08-05 23:59:59.993') or (UPLOAD_DATE BETWEEN '2017-08-12' AND '2017-08-19 23:59:59.993'))
and emp_id=t.emp_id) as counts
from [Vacation Audit Care 2017] t
group by t.emp_id
order by counts desc

示例数据

╔═════════════════╦═════════╗
║ Time_Stamp      ║ Emp_ID  ║
║ 7/20/2017 19:40 ║ 3140340 ║
║ 7/20/2017 19:40 ║ 2000950 ║
║ 7/20/2017 19:40 ║ 3118410 ║
║ 7/20/2017 19:40 ║ 311840  ║
║ 7/23/2017 21:19 ║ 3140340 ║
║ 7/23/2017 21:19 ║ 2000950 ║
║ 7/23/2017 21:19 ║ 3118410 ║
║ 7/23/2017 21:19 ║ 3124160 ║
║ 7/30/2017 7:00  ║ 3140340 ║
║ 7/30/2017 7:00  ║ 2000950 ║
║ 7/30/2017 7:00  ║ 3118410 ║
║ 7/30/2017 7:00  ║ 311840  ║
║ 8/6/2017 12:00  ║ 3140340 ║
║ 8/6/2017 12:00  ║ 3118410 ║
║ 8/6/2017 12:00  ║ 3124160 ║
║ 8/6/2017 12:00  ║ 311840  ║
║ 8/13/2017 12:00 ║ 3140340 ║
║ 8/13/2017 12:00 ║ 3118410 ║
║ 8/13/2017 12:00 ║ 3124160 ║
║ 8/13/2017 12:00 ║ 311840  ║
╚═════════════════╩═════════╝

预期输出

╔═════════╦════════╦═══════╦════════╗
║         ║ 30-Jul ║ 6-Aug ║ 13-Aug ║
║ emp_id  ║ wk2    ║ wk3   ║ wk4    ║
║ 3140340 ║ 2      ║ 3     ║ 4      ║
║ 2000950 ║ 2      ║       ║        ║
║ 3118410 ║ 2      ║ 3     ║ 4      ║
║ 311840  ║ 1      ║ 2     ║ 3      ║
║ 3124160 ║        ║ 1     ║ 2      ║
╚═════════╩════════╩═══════╩════════╝

根据预期输出使用7/23作为我的基础(第1周) 该表显示了预期的数据结果。 在第2周,311840第一次出现,所以我希望计数为1。

接下来的一周(8/6)311840在wk2中出现一次,在wk3中出现一次,所以我预计计数为2,而3124160首次出现,所以我希望计数为1等。

5 个答案:

答案 0 :(得分:2)

这将以您在样本中显示的格式显示结果。我在输出中前后加了一周。要删除那些额外的周,只需从枢轴中删除[29]和[33]。注释掉枢轴线以获取基础数据。

;WITH 
weekcounts AS (
    SELECT Time_Stamp, Emp_ID, DATEPART(week, Time_Stamp) AS int_week FROM sampleData
)

,counts AS (
    SELECT Emp_ID, int_week, 1 AS int_count
    FROM weekcounts
    UNION ALL
    SELECT weekcounts.Emp_ID, weekcounts.int_week, 1 AS int_count
    FROM weekcounts
        INNER JOIN counts
            ON weekcounts.Emp_ID = counts.Emp_ID
            AND (weekcounts.int_week - 1) = counts.int_week
)

,countsagg AS (
    SELECT Emp_ID, int_week, SUM(int_count) AS int_count
    FROM counts
    GROUP BY Emp_ID, int_week
)

SELECT * FROM countsagg
PIVOT (MAX(int_count) FOR int_week IN ([29],[30],[31],[32],[33])) piv

答案 1 :(得分:1)

这样的事情应该有效

SET DATEFIRST 1; --this will set Monday as first day of week.
SELECT EmpID, count(1)
from table
group by DATEPART(wk, timestamp), EmpID

答案 2 :(得分:1)

试试这个..它应该有效。我相信你想把这个月的每周分组。

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Daily Tracker Settings</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!-- Loading Bootstrap -->
    <link href="../dist/css/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">

    <!-- Loading Flat UI -->
    <link href="../dist/css/flat-ui.min.css" rel="stylesheet">

    <link rel="shortcut icon" href="img/favicon.ico">
</head>
<body>
    <form id="form1" runat="server" role="form">
        <div class="container">
            <div class="row mbl">
                <div class="col-md-12">
                    <h4>Plugin methods</h4>
                </div>
                <div class="col-md-12">
                    <form role="form">
                        <div class="form-group">
                            <label class="checkbox" for="checkbox100">
                                <input type="checkbox" data-toggle="radio" value="" id="checkbox100" required>
                                Checkbox

                            </label>
                        </div>
                        <button type="submit" class="btn btn-sm btn-primary">Submit</button>&nbsp;&nbsp;&nbsp;&nbsp;

                        <button class="btn btn-sm btn-default" data-radiocheck-check="#checkbox100">Check</button>
                        <button class="btn btn-sm btn-default" data-radiocheck-uncheck="#checkbox100">Uncheck</button>
                        <button class="btn btn-sm btn-default" data-radiocheck-toggle="#checkbox100">Toggle</button>&nbsp;&nbsp;&nbsp;&nbsp;

                        <button class="btn btn-sm btn-default" data-radiocheck-indeterminate="#checkbox100">Indeterminate</button>
                        <button class="btn btn-sm btn-default" data-radiocheck-determinate="#checkbox100">Determinate</button>&nbsp;&nbsp;&nbsp;&nbsp;

                        <button class="btn btn-sm btn-default" data-radiocheck-disable="#checkbox100">Disable</button>
                        <button class="btn btn-sm btn-default" data-radiocheck-enable="#checkbox100">Enable</button>&nbsp;&nbsp;&nbsp;&nbsp;

                        <button class="btn btn-sm btn-default" data-radiocheck-destroy="#checkbox100">Destroy</button>
                        <button class="btn btn-sm btn-default" data-radiocheck-init="#checkbox100">Init</button><br>
                        <br>
                    </form>
                </div>
            </div>
            <!-- /.row -->

        </div>


        <!-- jQuery (necessary for Flat UI's JavaScript plugins) -->
        <script src="../dist/js/vendor/jquery.min.js"></script>
        <!-- Include all compiled plugins (below), or include individual files as needed -->
        <script src="../dist/js/vendor/video.js"></script>
        <script src="../dist/js/flat-ui.min.js"></script>

        <script>
            $('button:not([type="submit"])').on('click', function (e) {
                var $this = $(this);

                if (!!$this.attr('data-radiocheck-check')) {
                    var el = $this.attr('data-radiocheck-check');
                    $(el).radiocheck('check');
                } else if (!!$this.attr('data-radiocheck-uncheck')) {
                    var el = $this.attr('data-radiocheck-uncheck');
                    $(el).radiocheck('uncheck');
                } else if (!!$this.attr('data-radiocheck-toggle')) {
                    var el = $this.attr('data-radiocheck-toggle');
                    $(el).radiocheck('toggle');
                } else if (!!$this.attr('data-radiocheck-indeterminate')) {
                    var el = $this.attr('data-radiocheck-indeterminate');
                    $(el).radiocheck('indeterminate');
                } else if (!!$this.attr('data-radiocheck-determinate')) {
                    var el = $this.attr('data-radiocheck-determinate');
                    $(el).radiocheck('determinate');
                } else if (!!$this.attr('data-radiocheck-disable')) {
                    var el = $this.attr('data-radiocheck-disable');
                    $(el).radiocheck('disable');
                } else if (!!$this.attr('data-radiocheck-enable')) {
                    var el = $this.attr('data-radiocheck-enable');
                    $(el).radiocheck('enable');
                } else if (!!$this.attr('data-radiocheck-destroy')) {
                    var el = $this.attr('data-radiocheck-destroy');
                    $(el).radiocheck('destroy');
                } else if (!!$this.attr('data-radiocheck-init')) {
                    var el = $this.attr('data-radiocheck-init');
                    $(el).radiocheck();
                }

                e.preventDefault();
            });

        </script>
    </form>
</body>
</html>

答案 3 :(得分:1)

感谢您提供示例数据,让问题更清晰,对未来访问此问题的其他人来说肯定更有用。

示例数据设置:

为了方便起见,我将您的示例数据弹出到table variable中定义并填充如下。

declare @emp_ts table
    (
        time_stamp datetime not null
        , emp_id int not null
    )

insert into @emp_ts 
values ('7/20/2017 19:40', 3140340),
('7/20/2017 19:40', 2000950),
('7/20/2017 19:40', 3118410),
('7/20/2017 19:40', 311840 ),
('7/23/2017 21:19', 3140340),
('7/23/2017 21:19', 2000950),
('7/23/2017 21:19', 3118410),
('7/23/2017 21:19', 3124160),
('7/30/2017 7:00 ', 3140340),
('7/30/2017 7:00 ', 2000950),
('7/30/2017 7:00 ', 3118410),
('7/30/2017 7:00 ', 311840 ),
('8/6/2017 12:00 ', 3140340),
('8/6/2017 12:00 ', 3118410),
('8/6/2017 12:00 ', 3124160),
('8/6/2017 12:00 ', 311840 ),
('8/13/2017 12:00', 3140340),
('8/13/2017 12:00', 3118410),
('8/13/2017 12:00', 3124160),
('8/13/2017 12:00', 311840 )

<强>答案:

我使用Recursive CTE生成周数,然后使用window function获取每周emp_id的运行总计数。得到了结果并pivoted它以预期的格式获得预期的周数。您可以将日期连接到列名称,但我认为提供的列名称将起作用。

; with wk_nbrs as
    (
        --recursive CTE that generates the week numbers.
        -- 7/23 thru 7/29 is Week 1
        select cast('2017-07-23' as date) as wk_bgn
        , cast('2017-07-29' as date) as wk_end
        , 1 as wk_nbr
        union all
        select dateadd(d,7,fw.wk_bgn) as wk_bgn
        , dateadd(d,7,fw.wk_end) as wk_end
        , fw.wk_nbr + 1 as wk_nbr
        from wk_nbrs as fw
        where 1=1
        and fw.wk_nbr < 100
    )
    , emp_wk_cnt as
    (
        --Getting the running total count of emp_id by week
        select a.emp_id
        , b.wk_nbr
        , count(*) over (partition by a.emp_id order by b.wk_nbr asc) as emp_wk_cnt
        from @emp_ts as a
        inner join wk_nbrs as b on cast(a.time_stamp as date) between b.wk_bgn and b.wk_end
        group by a.emp_id
        , b.wk_nbr  
    )
--pivoting the results out to final expected output
select post.emp_id
, post.wk2
, post.wk3
, post.wk4
from (
    select a.emp_id
    , 'wk' + cast(a.wk_nbr as varchar(10)) as wk_nbr
    , a.emp_wk_cnt
    from emp_wk_cnt as a
    ) as pre
pivot (sum(pre.emp_wk_cnt) 
        for pre.wk_nbr in 
            ([wk2],[wk3],[wk4])
    ) post
order by post.emp_id

<强>结果:

查询结果如下。你的预期输出和打击之间的唯一区别是emp_id 3124160,我认为wk3应该是2,wk 4应该是3,因为有问题的emp_id有以下{{1}的记录} S:

time_stamp

如果情况不是这样,请告诉我。

7/23/2017 21:19
8/6/2017 12:00
8/13/2017 12:00

答案 4 :(得分:1)

SELECT * 
   ,ROW_NUMBER() OVER(PARTITION BY EMPID ORDER BY [TIMESTAMP]) AS [ROWCOUNT]
   ,DATENAME(WEEK, timestamp) weeknum
   INTO #TMPweek
  FROM [Vacation Audit Care 2017]
  where timestamp>'2017-07-20 19:40:00.000'

   select distinct timestamp,  cast(day(timestamp) as nvarchar)+
   cast('-' as nvarchar)+cast(datename(m,[timestamp]) as nvarchar)+
   cast(' wk' as nvarchar) +cast(DATEPART(wk, timestamp) as nvarchar) weekname
   into #tw from #TMPweek

  select empid,[ROWCOUNT], weekname into #pvt
  from
  #TMPweek a
  inner join #tw b
  on a.timestamp=b.timestamp

  SELECT  empid, [23-July wk30], [30-July wk31], [6-August wk32], [13-August 
  wk33]
  FROM 
  (select empid,[ROWCOUNT], Weekname from #pvt
   ) AS ST
  PIVOT
  (
  SUM([ROWCOUNT])
  FOR Weekname IN ([23-July wk30], [30-July wk31], [6-August wk32], [13-August 
  wk33])
  ) AS PivotTable;

  OUTPUT -
  empid 23-July wk30    30-July wk31    6-August wk32   13-August wk33
  311840    NULL    1   2   3
  2000950   1   2   NULL    NULL
  3118410   1   2   3   4
  3124160   1   NULL    2   3
  3140340   1   2   3   4