2012-01-11 61 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