在WHERE / AND子句中为变量赋值

时间:2013-10-03 14:18:10

标签: sql sql-server tsql where

我正在处理一个相当大的SQL表达式,需要在查询的AND语句中列出三次。为了提高可读性,我想将表达式设置为变量,并将其引用3次。但是我正在努力解决这个问题。例如,我尝试了BEGIN SET ... END但它似乎是BEGIN块的无效位置。我也尝试引用顶级查询项(LowPrice),但无法识别。

以下是查询:

SELECT cl.claimid, cl.GUID1 AS [GUID1], cl.GUID2 AS [GUID2]
    ,cs.Conclusion AS [ClaimStatus]
    ,CASE [Type] WHEN 0 THEN 'a' + REPLACE(STR(Precedence,5),' ','0') ELSE 'b' + REPLACE(STR(Precedence,5),' ','0') END TransactionNumber
    ,tr.TradeDate AS [TradeDate]
    ,REPLACE(CONVERT(varchar(16),cast(Shares as money),1), ',', '') AS [Shares]
    ,tr.PricePerShare AS [Price]
    ,CASE WHEN tr.Custom IS NULL THEN '' ELSE tr.Custom END AS [ML]
    ,ISNULL((SELECT TOP 1 LowPrice FROM ca_historical_sec h 
        WHERE caseId = @caseid AND [Security] = 'Common Stock' AND h.TradeDate = tr.TradeDate
        ORDER BY tradeDate DESC),0) AS LowPrice
    ,ISNULL((SELECT TOP 1 HighPrice FROM ca_historical_sec h 
        WHERE caseId = @caseid AND [Security] = 'Common Stock' AND h.TradeDate = tr.TradeDate 
        ORDER BY tradeDate DESC),0) AS HighPrice
    ,CASE HasProof WHEN 1 THEN 'HAS PROOF' ELSE 'NO PROOF' END HasProof
FROM ca_claim cl
CROSS APPLY (
                --Get all fields of the top row
                SELECT TOP 100 PERCENT *
                FROM ca_transaction_sec tr 
                WHERE tr.claimId  = cl.claimid
                AND tr.type < 2
                AND (PricePerShare > 0 AND PricePerShare NOT BETWEEN
                     (
--- Trying to do it here ----
                      --BEGIN SET @ThePrice = ISNULL((SELECT TOP 1 LowPrice FROM ca_historical_sec h WHERE caseId = @caseid AND h.tradeDate = tr.tradeDate AND [Security] = 'Common Stock' ORDER BY h.tradeDate DESC),0) END
                      CASE WHEN @MarginType = 'Percent' THEN ISNULL((SELECT TOP 1 LowPrice FROM ca_historical_sec h WHERE caseId = @caseid AND h.tradeDate = tr.tradeDate AND [Security] = 'Common Stock' ORDER BY h.tradeDate DESC),0) - (ISNULL((SELECT TOP 1 LowPrice FROM ca_historical_sec h WHERE caseId = @caseid AND h.tradeDate = tr.tradeDate AND [Security] = 'Common Stock' ORDER BY h.tradeDate DESC),0) * @percentMargin)
                      ELSE ISNULL((SELECT TOP 1 LowPrice FROM ca_historical_sec h WHERE caseId = @caseid AND h.tradeDate = tr.tradeDate AND [Security] = 'Common Stock' ORDER BY h.tradeDate DESC),0) - @dollarMargin END
                     )
                     AND 
                     (
                      --Ideally this would be something like:
                      BEGIN SET @HighPrice = .... END
                      CASE WHEN @MarginType = 'Percent' THEN @HighPrice + (@HighPrice * @percentMargin)
                      ELSE @HighPrice + @dollarMargin END
                     )
                    )
                AND (@caseid <> 177 
                    OR (@caseid = 177 AND 0 = 0 AND ISNULL(tr.custom,'') in ('',' ','D')) 
                    OR (@caseid = 177 AND 0 = 1 AND tr.custom = 'A')) 
                order by tr.createdon
            ) tr
LEFT OUTER JOIN ca_ClaimStatus cs ON cl.claimid = cs.claimid
WHERE cl.caseId = @caseid

如您所见,ISNULL((SELECT TOP 1 LowPrice FROM ca_historical_sec h WHERE caseId = @caseid AND h.tradeDate = tr.tradeDate AND [Security] = 'Common Stock' ORDER BY h.tradeDate DESC),0)是一个很长的表达。此外,它已被列为CROSS APPLY之前的查询项之一。我想设置一个等于该值的变量。在保持CROSS APPLY时有没有办法做到这一点?

1 个答案:

答案 0 :(得分:0)

我可能会这样做:

;WITH cteHistCount As
(
    SELECT LowPrice, HighPrice, TradeDate
        , ROW_NUMBER() OVER(PARTITION BY TradeDate ORDER BY TradeDate DESC) As RowNum
    FROM ca_historical_sec 
    WHERE caseId = @caseid 
      AND [Security] = 'Common Stock' --AND h.TradeDate = tr.TradeDate
)
, cteHistTradeDate As
(
    SELECT * FROM cteHistCount WHERE RowNum = 1
)
SELECT cl.claimid, cl.GUID1 AS [GUID1], cl.GUID2 AS [GUID2]
    ,cs.Conclusion AS [ClaimStatus]
    ,CASE [Type] WHEN 0 THEN 'a' + REPLACE(STR(Precedence,5),' ','0') ELSE 'b' + REPLACE(STR(Precedence,5),' ','0') END TransactionNumber
    ,tr.TradeDate AS [TradeDate]
    ,REPLACE(CONVERT(varchar(16),cast(Shares as money),1), ',', '') AS [Shares]
    ,tr.PricePerShare AS [Price]
    ,CASE WHEN tr.Custom IS NULL THEN '' ELSE tr.Custom END AS [ML]
    ,tr.LowPrice
    ,tr.HighPrice
    ,CASE HasProof WHEN 1 THEN 'HAS PROOF' ELSE 'NO PROOF' END HasProof
FROM ca_claim cl
CROSS APPLY (
            --Get all fields of the top row
            SELECT TOP 100 PERCENT tr.*
                , ISNULL(h.LowPrice,0) As LowPrice, ISNULL(h.HighPrice,0) As HighPrice
            FROM ca_transaction_sec tr 
            LEFT OUTER JOIN cteHistTradeDate h ON h.TradeDate = tr.TradeDate
            WHERE tr.claimId  = cl.claimid
            AND tr.type < 2
            AND (PricePerShare > 0 AND PricePerShare NOT BETWEEN
                 (
                  CASE WHEN @MarginType = 'Percent' THEN ISNULL(h.LowPrice,0) 
                        - (ISNULL(h.LowPrice,0) * @percentMargin)
                       ELSE ISNULL(h.LowPrice,0) - @dollarMargin END
                 )
                 AND 
                 (
                  CASE WHEN @MarginType = 'Percent' THEN ISNULL(h.HighPrice,0) 
                        + (ISNULL(h.HighPrice,0) * @percentMargin)
                       ELSE h.HighPrice + @dollarMargin END
                 )
                )
            AND (@caseid <> 177 
                OR (@caseid = 177 AND 0 = 0 AND ISNULL(tr.custom,'') in ('',' ','D')) 
                OR (@caseid = 177 AND 0 = 1 AND tr.custom = 'A')) 
            order by tr.createdon
        ) tr
LEFT OUTER JOIN ca_ClaimStatus cs ON cl.claimid = cs.claimid
WHERE cl.caseId = @caseid