1

我有 2 张桌子UserSessionSale.

表有 4 列,UserUserIDUserSessionID和。SessionOpenDateSessionCloseDate

Sale有 2 列,分别是pricecost和。userIDCompletedDate

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

当用户仍处于登录状态时,用户可以进行一些销售,销售信息保存在Sale表中。销售完成时的时间戳保存在CompletedDate列中。

出于某种原因,我需要在必须在and内的某个特定UserSessionID位置完成所有销售。但是,如果用户还没有注销,这意味着 in 的值为 null,则 应该介于与 now 之间。CompletedDateSessionOpenDateSessionCloseDateSessionCloseDateCompletedDateSessionOpenDate

这是我的查询:

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'.and Incorrect syntax near ')'

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

4

3 回答 3

4

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

您可以IIF在 SQL Server 2012 中使用(语法糖CASE 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')
于 2013-02-06T06:33:17.970 回答
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' 或 and UserID = 'myuserid')

于 2013-02-06T06:48:44.387 回答
1

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

请参阅混合语句类型以进行完整讨论(披露:我自己的博客文章)。这里有一些片段。

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

剪...

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

剪...

既然您知道了三种主要类型的语句(并且我不排除存在更多或这些语句的子分类的可能性),您必须知道与 SQL Server 相处融洽的关键概念是,当某个一种声明是预期的,你不能使用不同的声明来代替它。

于 2013-02-06T07:06:09.133 回答