【问题标题】:Is there any equivalent to Postgresql EVERY aggregate function on other RDBMS?其他 RDBMS 上是否有任何与 Postgresql EVERY 聚合函数等效的函数?
【发布时间】:2012-05-02 03:33:47
【问题描述】:

每个聚合的文档:

every(expression) :如果所有输入值都为真,则为真,否则为假

http://www.postgresql.org/docs/9.1/static/functions-aggregate.html


EVERY 在语义上等价于 COUNT(conditionIsTrue) = COUNT(*)

select person_id, 

    every(visited_site = 'http://stackoverflow.com') as visited_same_site_forever,

    count(case when visited_site = 'http://stackoverflow.com' then '^_^' end) 
    = count(*) as visited_same_site_forever2

from z
group by person_id
order by person_id

输出:

 person_id | visited_same_site_forever | visited_same_site_forever2 
-----------+---------------------------+----------------------------
        88 | f                         | f
     55327 | t                         | t
    256196 | f                         | f

数据来源:

create table z(person_id int, visited_site varchar(100), datetime_visited timestamp);

insert into z values
(55327,'http://stackoverflow.com','Jan 1, 2010'),
(55327,'http://stackoverflow.com','Feb 14, 2012'),
(55327,'http://stackoverflow.com','May 1, 2012'),
(256196,'http://stackoverflow.com','February 1, 2012'),
(256196,'http://stackoverflow.com','February 2, 2012'),
(256196,'http://slashdot.org','May 2, 2012'),
(88,'http://theregister.co.uk','April 1, 2012'),
(88,'http://slashdot.org','April 2, 2012');

【问题讨论】:

    标签: database postgresql rdbms


    【解决方案1】:

    CASESUM()模拟EVERY()

    事实上,this article describes how EVERY() can be emulated via CASE and SUM()。以下两个语句是等价的:

    SELECT EVERY(id < 10)
    FROM book
    
    SELECT CASE SUM(CASE WHEN id < 10 THEN 0 ELSE 1 END) 
             WHEN 0 THEN 1 
             ELSE 0 
           END
    FROM book;
    

    EVERY() 窗口函数也是如此:

    SELECT 
      book.*, 
      EVERY(title LIKE '%a') OVER (PARTITION BY author_id)
    FROM book
    
    SELECT
      book.*,
      CASE SUM(CASE WHEN title LIKE '%a' THEN 0 ELSE 1 END)
           OVER(PARTITION BY author_id)
        WHEN 0 THEN 1 
        ELSE 0
      END
    FROM book;
    

    SQL 标准

    SQL:2008 标准提到了EVERY 聚合函数:

    10.9 <aggregate function>
    
    [...]
    
    <aggregate function> ::=
      COUNT <left paren> <asterisk> <right paren> [ <filter clause> ]
      | <general set function> [ <filter clause> ]
      | <binary set function> [ <filter clause> ]
      | <ordered set function> [ <filter clause> ]
    
    <general set function> ::=
      <set function type> <left paren> [ <set quantifier> ]
      <value expression> <right paren>
    
    <set function type> ::=
      <computational operation>
    
    <computational operation> ::=
      AVG
      | MAX
      | MIN
      | SUM
      | EVERY
      | [...]
    

    但“高级”SQL 标准功能通常不会由数据库实现。例如,Oracle 11g 不支持它,SQL Server 2012 也不支持。

    但是,使用HSQLDB,您可能会更幸运。 HSQLDB 2.x 非常符合标准,也是MySQL knows the BIT_AND() 聚合函数,它是EVERY() 的非标准别名,Postgres 也支持。

    注意,有些数据库允许编写用户定义的聚合函数,所以你不妨自己实现EVERY()

    【讨论】:

    • 这就是答案 :-) MySQL 可以将 BIT_AND 重命名为 BOOL_AND。 Postgresql 的 EVERY 是 BOOL_AND 的别名,Postgresql 也有 BIT_AND。现在尝试了 MySQL BIT_AND,它可以工作。然而,MySQL 没有正确的布尔值,但它的整数和布尔值之间存在对偶性,这就是为什么它的 BIT_AND 在功能上等同于 BOOL_AND/EVERY 无论如何。谢谢:-)
    • @Hao:是的,这些数据库相互复制了一些想法,所以你会看到到处都是相同的类似功能
    • @Hao:不确定这对你是否仍然重要,但我想出了一种方法来模拟EVERY()SUM()CASE...
    • @LukasEder Oracle 20c: BIT_AND_AGG SELECT BIT_AND_AGG(CASE WHEN visited_site = 'http://stackoverflow.com' THEN 1 ELSE 0 END) FROM book
    猜你喜欢
    • 1970-01-01
    • 2020-12-08
    • 2012-06-05
    • 2017-09-11
    • 2018-10-17
    • 2015-12-26
    • 1970-01-01
    • 2019-12-20
    • 1970-01-01
    相关资源
    最近更新 更多