如何比较元组的特定值与 SQL 中两个表的 AVG 值

How to compare specific Values of tuples with an AVG-value in SQL over two tables

我正在搜索一个查询,其中可以 "join" 具有所有元组的特定值的 AVG 值。

所以我有以下数据(主题是关于公司的数据集):

表 1: ID 姓名国家/地区 Class

表2: ID 值 1 值 2

我设法获得了特定国家/地区的 Value1/Value2 和一家公司的 Class 的 AVG 值。 现在,我试图显示 Country/Class 的公司数量,这些公司在其 class 的 AVG 值的 5% 值范围内。 我尝试了所有我能想象到的可能性。我正在努力解决的问题是,在嵌套查询中不可能返回多个值。

谁能给我一个解决这个问题的方法?

我认为你需要这样的东西:

with data as (
  select cname, country, class, value1/value2 vv
      , avg(value1/value2) over (partition by country, class) av
    from vals join companies using (id) )
select country, class, count(case when vv/av < 0.2 then 1 end) cnt
  from data group by country, class

SQLFiddle

它是如何工作的?在每个 id 的第一步中,我们收集有关按国家/地区划分的平均值 (value1/value2) 和 class 的信息。 这是子查询data中的列av,使用解析函数avg()进行计算。这个子查询的输出是:

CNAME      COUNTRY    CLASS         VV         AV
---------- ---------- ----- ---------- ----------
GHI        China      A             30         30
ABC        Russia     A              5       32,5
JKL        Russia     A             60       32,5
DEF        Russia     B              3          3

接下来我们只需要按国家/地区和 class 对数据进行分组,并附上符合您条件的公司数量的信息。 所以完整查询的输出是(我使用了 20%,将条件 vv/av < 0.2 更改为您需要的任何内容):

COUNTRY    CLASS        CNT
---------- ----- ----------
Russia     A              1
China      A              0
Russia     B              0

您可以通过将 AVG() 用作 window(分析)函数来执行此操作:

SELECT id, name, country, class, company_value FROM (
    SELECT t1.id, t1.name, t1.country, t1.class, t2.value1/t2.value2 AS company_value
         , AVG(t2.value1/t2.value2) OVER ( PARTITION BY t1.country, t1.class ) AS avg_value
      FROM table1 t1 INNER JOIN table2 t2
        ON t1.id = t2.id
) WHERE company_value BETWEEN avg_value * 0.95 AND avg_value * 1.05;

在上面的查询中,我使用 0.951.05 分别表示 1 - 0.051 + 0.05(在 5% 以内)。要获得计数,只需使用上面的作为子查询(或者 CTE,如果你更习惯的话):

SELECT country, class, COUNT(*) FROM (
    SELECT id, name, country, class, company_value FROM (
        SELECT t1.id, t1.name, t1.country, t1.class, t2.value1/t2.value2 AS company_value
             , AVG(t2.value1/t2.value2) OVER ( PARTITION BY t1.country, t1.class ) AS avg_value
          FROM table1 t1 INNER JOIN table2 t2
            ON t1.id = t2.id
    ) WHERE company_value BETWEEN avg_value * 0.95 AND avg_value * 1.05
);