1

私は2つのテーブルUserSessionSale.

テーブルには、、 のUser4 つの列があります。UserIDUserSessionIDSessionOpenDateSessionCloseDate

表には、、およびSaleの 2 つの列があります。pricecostuserIDCompletedDate

Userユーザーがログインすると、テーブルに新しい行が作成され、ユーザーのログイン タイムスタンプが に保存され、SessionOpenDate新しい行がUserSessionIDセッションに割り当てられます。ユーザーがログオフすると、ログオフのタイムスタンプが に保存されSessionCloseDateます。

ユーザーがまだログインしている場合、ユーザーは販売を行うことができ、販売情報がSaleテーブルに保存されます。CompletedDate保存された列で販売が確定したときのタイムスタンプ。

なんらかの理由で、が と 内にある必要がある特定のUserSessionID場所ですべての販売を完了する必要があります。ただし、ユーザーがまだログオフしていない場合、つまり の値が 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実際に何を達成しようとしているのかわかりません。SETcloseTime

IIFSQL 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' または UserID = 'myuserid' を追加できます)

于 2013-02-06T06:48:44.387 に答える
1

他の人は特定の問題を説明し、「あなたに魚を与えた」. でも「釣り方を教えてあげたい」。

完全な議論については、 mixed-up statement typesを参照してください(開示: 私自身のブログ投稿)。ここにいくつかのスニペットがあります。

式は、演算子で結合された 1 つ以上のリテラル値または関数で構成され、正しい順序で評価されると、値または値のコレクションになります。

をちょきちょきと切る...

従わなければならないいくつかの手順があるため、手続き型ステートメントと呼ばれます。単一の値が得られる操作順序の単純なケースではありません。実際には、まったく表現された値はありません。

をちょきちょきと切る...

主な 3 種類のステートメントを理解したので (さらに多くのステートメントが存在する可能性や、これらの下位分類が存在する可能性を排除するつもりはありません)、SQL Server とうまくやっていくために知っておくべき重要な概念は、特定のステートメントがの種類のステートメントが予期されているため、その代わりに別のステートメントを使用することはできません。

于 2013-02-06T07:06:09.133 に答える