SQL Server:如何遍历行并分配值

时间:2012-10-17 18:46:28

标签: sql-server-2008

我有几张表要处理。一个是这样的:

dbo.userActivity

 userID    Action    Time
   1         25       12:00
   1         10       12:01
   1         12       12:35
   1          6       13:54
   2         10        6:47
   2         42        6:48
   3          8       11:54
   etc.

另一张表是一个如下所示的时间表:

dbo.userSchedule

 userID    schedule_start    schedule_stop
   1            07:00            09:00
   2            11:00            12:30
   3            14:00            15:00
  etc.

我需要为dbo.userActivity中的每一行执行的操作是确定每个操作是在schedule_start之前一小时,在schedule_startschedule_stop次之间,一小时在schedule_stop之后,或任何其他时间。

所以我需要在dbo.userActivity附加一个列,其值为“之前”,“期间”,“之后”,“其他”基于时间计算。

我真的不知道该怎么做,并感谢你们所能提供的任何帮助。

编辑:

好的,所以我有大部分工作。我刚刚看到了一些我将要处理的实际数据,并注意到活动时间是完整的日期时间戳,而活动时间表恰好在时间上。所以我需要将日期时间转换为我可以比较的东西。

这看起来很有效:

  

SELECT *   从     (         SELECT CONVERT(TIME,SCANDATE)as scanTime         来自appData     )st   在哪里st.scanTime< ='6:00'   ORDER BY st.scanTime

仅作为一个例子。但是当我尝试将其合并到下面的case语句中时,它就不起作用了。它对每一行应用相同的THEN。

SELECT
  CASE
  WHEN EXISTS
  (
  SELECT *
  FROM
  (
  SELECT CONVERT(TIME, SCANDATE) as scanTime 
  FROM appData
  ) st
  WHERE st.scanTime <= '6:00'
  )
  THEN 'Before 6 am'

  ELSE '6 am or after'
  END
FROM appData

对此有何进一步的想法?

1 个答案:

答案 0 :(得分:1)

首先,您需要将列(NULL)添加到表中。

ALTER TABLE dbo.UserActivity
ADD TimeStatus VARCHAR(6) NULL;

接下来,您将编写更新查询。它可以用CASE语句编写:

UPDATE ua
SET ua.TimeStatus =
   CASE
      WHEN CAST(ua.Time AS TIME) >= us.Schedule_Start
         AND CAST(ua.Time AS TIME) <= us.Schedule_stop THEN 'During'
      WHEN CAST(ua.Time AS TIME) >= DATEADD(HOUR, -1, us.Schedule_Start)
         AND CAST(ua.Time AS TIME) <= us.ScheduleStart THEN 'Before'
      WHEN CAST(ua.Time AS TIME) >= us.Schedule_Stop
         AND CAST(ua.Time AS TIME) <= DATEADD(HOUR, 1, us.Schedule_Stop)
         THEN 'After'
      ELSE 'Other'
   END
FROM dbo.UserActivity AS ua
INNER JOIN dbo.userSchedule AS us ON ua.UserId = us.UserId

如果所有列都包含数据,则可以将列设置为NOT NULL,如果您已更新应用程序以了解并填充此新列。


我还会考虑不将字符串值存储在此表中,而是将较小的值存储在引用表的外键中。只有4个值,您可以使用TINYINT并为您存储的每个dbo.UserActivity记录节省空间。

如果您决定使用此路线,则只需从参考表中获取值,并将字符串值替换为ID值。如果Before = 0,则在= 1,After = 2,其他= 3

UPDATE ua
SET ua.TimeStatusId =
   CASE
      WHEN CAST(ua.Time AS TIME) >= us.Schedule_Start
         AND CAST(ua.Time AS TIME) <= us.Schedule_stop THEN 1
      WHEN CAST(ua.Time AS TIME) >= DATEADD(HOUR, -1, us.Schedule_Start)
         AND CAST(ua.Time AS TIME) <= us.ScheduleStart THEN 0
      WHEN CAST(ua.Time AS TIME) >= us.Schedule_Stop
         AND CAST(ua.Time AS TIME) <= DATEADD(HOUR, 1, us.Schedule_Stop)
         THEN 2
      ELSE 3
   END
FROM dbo.UserActivity AS ua
INNER JOIN dbo.userSchedule AS us ON ua.UserId = us.UserId

然后,您将获得带有INNER JOIN的UI的文本值到您的TimeStatus参考表