复杂存储过程中的if-then-else构造

时间:2015-11-26 15:49:04

标签: sql sql-server stored-procedures

我对sql查询比较新,我想知道如何创建一个复杂的存储过程。我的数据库在SQL服务器上运行。

我有一个表customer(id,name)和一个表customer_events(id,customer_id,timestamp,action_type)。我想将一个计算字段customer_status添加到表客户

  • 0 :(如果customer_events中没有此客户的事件)或(最近的事件是> 5分钟前)
  • 1:如果最近的事件是< 5分钟前和action_type = 0
  • 2:如果最近的事件是< 5分钟前和action_type = 1

我可以使用if-then-else结构,还是应该以不同的方式解决这个挑战?

2 个答案:

答案 0 :(得分:0)

假设您将事件信息输入“Most_Recent_Event_Mins_Ago”。如果没有,它将是NULL。

SELECT Id, Name,
       CASE 
          WHEN Most_Recent_Event_Mins_Ago IS NULL THEN 0
          WHEN Most_Recent_Event_Mins_Ago <5 AND Action_type = 0 THEN 1
          WHEN Most_Recent_Event_Mins_Ago <5 AND Action_type = 1 THEN 0
          ..other scenarions
          ELSE yourDefaultValueForStatus
       END as Status
FROM customer
WHERE
...
...

答案 1 :(得分:0)

正如您在评论中提到的,您实际上想要向选择查询添加字段,并且在一般意义上,您想要的是CASE语句。他们的工作方式如下:

SELECT field1, 
       field2,
       CASE
         WHEN some_condition THEN some_result
         WHEN another_condition THEN another_result
      END AS field_alias
FROM table

应用于您的特定场景,这并非完全直截了当。您肯定需要left join您的状态表,您还希望聚合以查找最新事件以及该事件的操作类型。一旦掌握了这些信息,案例陈述就很简单。

在没有数据访问权限的情况下编写sql总是很难,但是类似于:

SELECT c.id, 
       c.name,
       CASE 
          WHEN e.id IS NULL OR DATEDIFF(minute,e.timestamp,getDate())>=5 THEN 0
          WHEN DATEDIFF(minute,e.timestamp,getDate())<5 AND s.action_type=1 THEN 1
          WHEN DATEDIFF(minute,e.timestamp,getDate())<5 AND s.action_type=0 THEN 2
       END as customer_status
FROM clients c
LEFT JOIN (
    SELECT id, client_id, action_type, 
           rank() OVER(partition by client_id order by timestamp desc) AS r
    FROM customer_events
) e
ON c.id=e.client_id AND e.r=1

这个核心是中间的子查询,它使用rank功能通过按时间戳降序排序的client_id为每个状态提供一个数字。因此,排名为1的每个记录都将是最新的(对于该客户端)。此后,您只需将其加入到客户端表中,并使用它来确定customer_status的正确值