如果EXISTS阻止

时间:2013-02-06 06:27:36

标签: sql sql-server

我有2个表UserSessionSale

User有4列,即UserIDUserSessionIDSessionOpenDateSessionCloseDate

Sale有2列,分别是pricecostuserIDCompletedDate

当用户登录时,会在User表中创建一个新行,其中用户的登录时间戳将保存在SessionOpenDate中,并且新的UserSessionID将被分配给会议。当用户注销时,注销时间戳将保存在SessionCloseDate

当用户仍然登录时,用户可以进行一些销售,销售信息保存在Sale表中。销售最终确定的时间戳已保存在CompletedDate列中。

由于某些原因,我需要在某个UserSessionID内完成所有销售,其中CompletedDate必须在SessionOpenDateSessionCloseDate之内。但是,如果用户尚未注销,这意味着SessionCloseDate中的值为空,则CompletedDate应介于SessionOpenDate和现在之间。

这是我的疑问:

SELECT SUM(s.cost) AS Cost, SUM(s.price) AS Price
FROM Sale AS s 
  INNER JOIN UserSession AS u 
  ON s.userID = u.userID
WHERE 
  (s.CompletedDate >=
    ( SELECT SessionOpenDate
      FROM UserSession
      WHERE (UserSessionID = u.UserSessionID)
)
  ) 
  AND 
  (s.CompletedDate < 
    ( 
      IF EXISTS
       (    
         SELECT SessionCloseDate AS closeTime
         FROM UserSession AS UserSessionTemp
         WHERE (UserSessionID = u.UserSessionID)
       ) 
       BEGIN
         SET closeTime = SELECT CURRENT_TIMESTAMP
       END
    )
  ) 
  AND u.UserSessionID IN (1) 

但是,Sql Server说Incorrect syntax near the keyword 'IF'.Incorrect syntax near ')'

有谁能告诉我我的IF块出了什么问题?

由于

3 个答案:

答案 0 :(得分:4)

您不能在IF语句中使用SELECT块。此外,由于SET不是变量/参数,因此我不知道您真正想要使用closeTime完成什么。

您可以在SQL Server 2012中使用IIFCASE WHEN <condition> THEN <true_value> ELSE <false_value> END的语法糖 - 在早期版本中使用此语法):

IIF(EXISTS
   (    
     SELECT SessionCloseDate AS closeTime
     FROM UserSession AS UserSessionTemp
     WHERE (UserSessionID = u.UserSessionID)
   ), (
     SELECT SessionCloseDate AS closeTime
     FROM UserSession AS UserSessionTemp
     WHERE (UserSessionID = u.UserSessionID)
   ),  
     CURRENT_TIMESTAMP
)

老实说,不要太复杂,这就是我要做的事情:

SELECT SUM(s.cost) AS Cost, SUM(s.price) AS Price
FROM userSession AS u
INNER JOIN Sale AS s ON u.userID = s.userID 
WHERE u.UserSessionID = @UserSessionId
AND s.CompletedDate >= u.SessionOpenDate 
AND (u.SessionCloseDate IS NULL OR s.CompletedDate < u.SessionCloseDate)

或者,

SELECT SUM(s.cost) AS Cost, SUM(s.price) AS Price
FROM userSession AS u
INNER JOIN Sale AS s ON u.userID = s.userID 
WHERE u.UserSessionID = @UserSessionId
AND s.CompletedDate BETWEEN u.SessionOpenDate 
                    AND COALESCE(u.SessionCloseDate, '12/31/9999 23:59:59.9999')

答案 1 :(得分:2)

我会选择这样的东西,这取决于你在寻找什么。我不知道你是否想要特定用户或会话的信息,但这很简单,可以添加。

SELECT UserSessionID, SUM(cost) AS TotalCost, SUM(price) AS TotalPrice
FROM UserSession LEFT OUTER JOIN sale
ON UserSession.userid = sale.userid AND
   ((UserSession.SessionCloseDate IS NULL AND sale.CompletedDate BETWEEN UserSession.SessionOpenDate AND GetDate())
   OR (sale.SessionCloseDate IS NOT NULL AND sale.CompletedDate BETWEEN UserSession.SessionOpenDate AND UserSession.SessionCloseDate))
WHERE SUM(cost) > 0
GROUP BY UserSessionID

(如果您不想要完整列表,可以在组上方添加AND UserSessionID ='mysessionid'或UserID ='myuserid')

答案 2 :(得分:1)

其他人已经解释了具体问题和“给你一条鱼”。不过,我想“教你如何钓鱼”。

请参阅mixed-up statement types进行全面讨论(披露:我自己的博文)。这是一些片段。

  

表达式由一个或多个与运算符绑定在一起的文字值或函数组成,当以正确的顺序计算时,会生成值或值集合。

...剪断

  

调用过程语句,因为必须遵循一些过程。这不是一个简单的操作顺序,导致单个值。实际上根本没有表达任何价值。

...剪断

  

现在您已经了解了三种主要语句(并且我不排除存在更多或者存在更多这些语句的可能性),您必须知道与SQL Server相处的关键概念是当预期某种陈述时,你不能在其中使用不同的陈述。

我希望这对你有所帮助。