【问题标题】:Conditional probability p(y|x) in SQLSQL 中的条件概率 p(y|x)
【发布时间】:2016-12-03 12:42:11
【问题描述】:

如何在与供应商无关的 SQL 代码中计算条件概率,同时仅读取一次预先计算的表(直方图)?

假设我们有一个返回直方图关系的查询。 直方图包含以下属性:{x, y, cnt},其中cnt 是名义属性 xy 的出现次数。 直方图的计算非常耗时。

一旦我们有了直方图,我们就想计算条件概率p(y|x)。如何做到这一点的一种可能方法是采用 p(y|x) = count(y,x) / count(x),如以下查询中所述:

with histogram as (
    // Long and time consuming subquery returning {x, y, cnt}
), x_count as (
    select x
         , sum(cnt) as cnt
    from histogram
    group by x
) 
select y
     , x
     , cnt/x_count.cnt as probability 
from histogram 
join x_count
using(x)

但是,公用表表达式 (CTE) 是不可移植的(例如 MySQL 不能使用它们)。有没有办法重写 CTE:

  1. 可以在 MySQL、MSSQL 和 PostgreSQL 上执行相同的查询而不需要更改?
  2. 关系直方图只计算一次?

我能想到的就是将直方图具体化为一个表格。处理直方图。并删除直方图

【问题讨论】:

标签: mysql sql sql-server postgresql


【解决方案1】:

首先,仅仅因为您将某些东西声明为 CTE 并不意味着它只运行一次。例如,SQL Server 不会具体化 CTE,因此使用您的逻辑,它将为每个引用运行一次直方图。和视图一样。

此外,并非所有数据库都支持using 子句。

因此,您可以做的与供应商无关的一件事是使用视图。有一个小问题,因为删除已经存在的视图是特定于供应商的。但以下通常可以表达查询:

create view histogram as  -- you might want to give this a more unique name
    // Long and time consuming subquery returning {x, y, cnt}

select h.y, h.x, cnt / total.cnt as probability 
from histogram h join
     (select x, sum(cnt) as cnt
      from histogram
      group by x
     ) total
     on h.x = total.x;

drop view histogram;

当然,这会多次运行直方图查询。所以,您可以使用临时表解决这个问题:

create table histogram (
    x ??,  -- I don't know what the types are
    y ??,
    cnt ??
);

insert into histogram (x, y, cnt)
    select . . . ;  -- your complicated query here

select y, x, cnt * 1.0 / total.cnt as probability 
from histogram h join
     (select x, sum(cnt) as cnt
      from histogram
      group by x
     ) total
     on h.x = total.x;

drop table histogram;

不幸的是,删除现有 表是特定于数据库的。不过,这确实符合您的要求。

我的建议是从需求中删除 MySQL——从 ANSI 功能的角度来看,它相当退化。然后简单地做:

select h.*, cnt * 1.0 / sum(cnt) over (partition by x) as probability
from histogram h;

* 1.0 是因为某些数据库会进行整数除法,而cnt 听起来可能是整数。)

这将是表示查询的最简单方法,无需重新计算histogram。而且,它适用于很多数据库——SQL Server、Postgres、Oracle、Teradata、DB2、BigQuery、RedShift、Hive。事实上,我认为它几乎适用于通常称为“数据库”的所有当前版本,除了 MySQL、SQLite 和 MS Access。

【讨论】:

    猜你喜欢
    • 2021-06-26
    • 2013-12-15
    • 2022-07-01
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    • 2020-10-08
    • 2016-08-11
    • 1970-01-01
    相关资源
    最近更新 更多