2012-01-11 95 views
4

大多數數據庫都有類似GREATEST函數,這可能會有用一些。至少這些數據庫沒有這樣的功能:如何模擬Sybase ASE中的GREATEST()?

  • 德比
  • SQL服務器
  • Sybase ASE的
  • Sybase SQL Anywhere的

對於SQL Server和Sybase SQL Anywhere的,在函數可以使用子查詢和UNION ALL進行模擬,可以在this question here中看到。例如:

-- SELECT GREATEST(field1, field2, field3) FROM my_table 
SELECT (SELECT MAX(c) FROM 
        (SELECT my_table.field1 AS c UNION ALL 
         SELECT my_table.field2  UNION ALL 
         SELECT my_table.field3) T) AS greatest 
FROM my_table 

但是這在Sybase ASE中不起作用。顯然,子查詢不能訪問外部查詢的my_table引用。我得到的錯誤是

列前綴'my_table'與查詢中使用的表名或別名不匹配。無論是在FROM子句中未指定該表,還是必須使用相關名稱

請注意,Sybase SQL Anywhere不會出現此問題。任何想法這裏有什麼問題以及如何重新編寫查詢?

我想避免

  • 存儲功能,我可以不具有必要的補助來創建它們
  • 冗長CASE表達式,與所需的所有比較的組合排列的表達長度嵌套0​​表達至少O(n^2)n是參數GREATEST
+1

MySQL有與導出表同樣的限制,以及(儘管中當然它確實有'最好'的功能!)。 – 2012-01-11 20:09:57

+0

@MartinSmith:你說的對,我只是試過用MySQL ...有趣的... – 2012-01-11 20:14:50

回答

2

據我瞭解,邏輯(忽略空值)是

SELECT CASE 
      WHEN field1 >= field2 
       AND field1 >= field3 
      THEN field1 
      WHEN field2 >= field3 
      THEN field2 
      ELSE field3 
     END AS greatest 
    FROM my_table; 

...但應該只返回空當所有值都爲空。


我覺得這是更如何我希望能夠做的事情(雖然,Sybase ASE的不支持通用表表達式):

WITH my_table 
    AS 
    (
     SELECT * 
     FROM (
       VALUES ('A', 1, 2, 3), 
        ('B', 2, 3, 1), 
        ('C', 3, 1, 2), 
        ('D', NULL, 2, 3), 
        ('E', NULL, NULL, 3), 
        ('F', NULL, 3, NULL), 
        ('G', 1, NULL, 3), 
        ('H', 1, 3, NULL), 
        ('X', NULL, NULL, NULL) 
      ) AS T (ID, field1, field2, field3) 
    ), 
    T1 
    AS 
    (
     SELECT ID, field1 AS field_n 
     FROM my_table 
     UNION 
     SELECT ID, field2 AS field_n 
     FROM my_table 
     UNION 
     SELECT ID, field3 AS field_n 
     FROM my_table 
    )   
SELECT ID, MAX(field_n) AS greatest 
    FROM T1 
GROUP 
    BY ID; 
+0

好點提到'NULL'。實際上'GREATEST(1,2,NULL)'應該返回NULL,而不是2.無論如何,對於少量的字段,這可能效果最好。但對於任意數字,「CASE」表達式可能會爆炸...... – 2012-01-12 12:30:53

+0

@LukasEder是指任意數字還是任意數量的字段? – 2012-01-12 14:35:27

+0

@aF。是的,'GREATEST(1,2,NULL)'只是一個例子。 – 2012-01-12 14:46:41

0

數量在這種情況下,我會添加一個額外的CASE

SELECT 
    CASE WHEN field1 IS NOT NULL 
      AND field2 IS NOT NULL 
      AND field3 IS NOT NULL THEN 
     CASE WHEN field1 >= field2 
       AND field1 >= field3 
      THEN field1 
      WHEN field2 >= field3 
      THEN field2 
      ELSE field3 
     END 
    ELSE 
     NULL 
    END AS greatest 
    FROM my_table 
+0

我想模擬「GREATEST()」函數本身的任意用例。我懷疑我應該爲此創建臨時表......此外,您的示例將從整個表中選擇整體最大值,即MAX(GREATEST(field1,field2,field3))'。我只對'GREATEST(field1,field2,field3)' – 2012-01-12 12:37:16

+0

@LukasEder感興趣,你想從每一行中獲得最大的? – 2012-01-12 13:32:00

+0

我對特定的解決方案沒有特別的問題。我想一般地模擬'GREATEST()'函數。我希望能夠做到「GROUP BY GREATEST(a,b,c)'或'ORDER BY GREATEST(a,b,c)'或'WHERE GREATEST(a,b,c)= LEAST(d, e,f)'等等。正如我在我的問題中提出的那樣。建議的表達式在許多數據庫(包括SQL Server)中都有效但不是在Sybase ASE(或Derby或MySQL)中......說了這些之後,我不一定需要每行中最好的。我想要任何'最好的(a,b,c)''不管'a,b,c'是什麼。這就是我所說的「模擬」 – 2012-01-12 13:39:23

0

下面的SQL子句是更簡潔比onedaywhen's answer,雖然他們是語義上等效:

SELECT CASE WHEN field1 >= ALL(field2, field3, field4) THEN field1 
      WHEN field2 >= ALL(  field3, field4) THEN field2 
      WHEN field3 >= ALL(    field4) THEN field3 
                 ELSE field4 
     END AS greatest 
FROM my_table; 

這是最後一個罕見的,但漂亮的用例的,幾乎沒有人在SQL使用這些量詞。也看到這個問題:

Are SQL ANY and SOME keywords synonyms in all SQL dialects?

不幸的是,這個語法是不是在所有的SQL方言的支持,作爲ALL量詞後容易需要一個<table subquery>

+0

SQL標準要求'ALL'量詞具有'<表子查詢>',所以這必須是一個擴展。你知道哪些SQL實現支持這個嗎? (SQL Server不支持它。) – onedaywhen 2012-01-30 13:00:01

+0

@onedaywhen:至少[Postgres](http://www.postgresql.org/docs/9.1/static/functions-comparisons.html#AEN17416)和[Oracle](http ://docs.oracle.com/cd/B19306_01/server.102/b14200/conditions002.htm#sthref2733)有一些語法擴展 – 2012-01-30 20:47:23