2013-10-03 44 views
1

我正在處理需要在查詢的AND語句中列出三次的相當大的SQL表達式。爲了提高可讀性,我想將表達式設置爲一個變量,並引用它3次。不過,我無法正在進行這項工作。例如,我嘗試了BEGIN SET ... END,但它似乎是BEGIN塊的無效位置。我也嘗試引用頂級查詢項目(LowPrice),但沒有被識別。將值賦給WHERE/AND子句中的變量

這裏的查詢:

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之前的其中一個查詢項目。我想設置一個等於該值的變量。有沒有辦法做到這一點,而保持交叉應用?

+0

壞主意,SQL是不是像一個面向對象的語言。留下多個參考。 – HLGEM

+0

我會從一個概念證明開始,在那裏它使用一個非常簡單的(虛擬)查詢,然後用您的實際查詢替換虛擬。 –

+0

您可以使用動態SQL重複表達式來簡化該部分,但會引入其他複雜性。可能會使它變得更好,可能會使它變得更好,可能會變得更糟。有很多方法可以重構查詢(或將其分解爲多個),但我認爲我同意@PieterB - 從一些簡單的事情開始。 –

回答

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