簡體   English   中英

MySQL:在同一SELECT語句中重用用戶定義的變量

[英]MySQL: Re-using user-defined variables in the same SELECT statement

我在stackoverflow中進行了搜索,但沒有完全找到我的問題的確切答案,因此,如果可以的話,請幫助我。

我“想”建立一個像這樣的SQL語句:

SELECT
  @tax1 := (complicated calculation formula),
  @owe := (another complicated calculation formula),
  IF(@owe=0, 0,@tax1/@owe)
FROM ...

但是,在關於用戶定義變量的 MySQL文檔中,建議不要這樣說:

通常,永遠不要為用戶變量分配值,並且不要在同一條語句中讀取該值。 您可能會得到預期的結果,但這不能保證。 涉及用戶變量的表達式的求值順序是不確定的,並且可能根據給定語句中包含的元素而改變; 此外,在MySQL服務器的發行版之間,不能保證此順序相同。 在SELECT @a,@a:= @ a + 1,...中,您可能認為MySQL將首先評估@a,然后再進行賦值。 但是,更改語句(例如,通過添加GROUP BY,HAVING或ORDER BY子句)可能導致MySQL選擇評估順序不同的執行計划。

我的目標是避免復制和粘貼那些非常復雜的公式,因為它會影響可讀性,並且如果該公式每次更改,我都必須確保在所有地方都對其進行了更改-但這樣做確實可以使它正常工作精細。

另外,我知道ALIAS 不起作用,因為別名僅在GROUP BY,HAVING和ORDER子句中起作用。

我讀過其他一些文章,先做一個子查詢來計算@ tax1和@owe,然后再使用另一個查詢來組合結果。 但是我認為性能可能不僅僅只是簡單地復制並粘貼這些公式而已。

有沒有人建議他們會做什么? 還是我在可讀性和性能之間做出選擇?

提前致謝。

是的,在沒有用戶變量的SQL中執行此操作的唯一方法是編寫派生表子查詢。 然后,您可以使用列別名來引用這些復雜表達式的結果:

SELECT tax1, owe, IF(owe=0, 0,tax1/owe) AS ratio
FROM (
  SELECT
    (complicated calculation formula) AS tax1,
    (another complicated calculation formula) AS owe
  FROM ...
) AS _sub

MySQL在優化子查詢方面存在一些問題,但是派生表的情況並不是壞情況之一。

關於MySQL和子查詢的警告是關於在WHERE子句的范圍條件下使用子查詢。 MySQL無法確定子查詢是常量,因此即使不需要,它也會將子查詢作為依賴子查詢重復進行重新評估。

我經常在select語句中使用變量進行順序評估,匯總,組統計和數據分類。

這是一個示例:

MySQL列出每個類別的前X條記錄,並將每條記錄與其之前的差異組合在一起

create table if not exists 
        closemovers engine=memory 
select 
          code 
        , date 
        , close 
        , rank 
        , prevclose 
        , sign 
        , cumm 
from 
        ( select 
                  `code` 
                , `date` 
                , `close` 
                , @rank := if( @code = code , @rank + 1 , 1) as rank 
                , @prevclose := if( @code = code , cast( @prclose as decimal(10,3) ), null) as prevclose 
                , if(@code = code, sign( @prclose - close), NULL) as sign 
                , @cumm := if(@code = code and @psign = sign(@prclose - close), @cumm + 1 , 1) as cumm
                , @psign := sign(@prclose - close) 
                , @code := code
                , @prclose := close 
        from 
            companyhistory 
        order by 
            code, date 
         ) as ranked 
 join 
        pricefeed 
                using (code) 
where 
        rank < 10 
        and sign is not null ;

我希望這可以給您提示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM