查找与列的平均值匹配的行

Finding rows which match the average value of a column

我正在使用 Oracle 11g。我有几张看起来像这样的表格(稍微简化了一点)。

CREATE TABLE clients (
    id NUMBER(10) NOT NULL,
    gridx NUMBER(10),
    gridy NUMBER(10),
    CONSTRAINT clients_pk PRIMARY KEY (id)
);

CREATE TABLE requests (
    id NUMBER(10) NOT NULL,
    client_id NUMBER(10),
    CONSTRAINT clients_fk FOREIGN KEY (client_id) REFERENCES clients(id),
    CONSTRAINT requests_pk PRIMARY KEY (id)
);

我需要找到看到平均请求数的网格部分。到目前为止,我提出了以下查询,其中列出了为每个不同的网格位置发出的请求数。

SELECT joined_tbl.gridx, joined_tbl.gridy, COUNT(joined_tbl.id) requests_cnt FROM (
    SELECT c.gridx, c.gridy, r.id
    FROM requests r
    INNER JOIN clients c ON c.id=r.client_id GROUP BY c.gridx, c.gridy, r.id ORDER BY r.id
) joined_tbl
GROUP BY joined_tbl.gridx, joined_tbl.gridy;

这给出了以下输出

 GRIDX      GRIDY REQUESTS_CNT
     1         -3            2
     2          5            4
    -1         -3            4
    -3         -2            6

接下来我需要取 REQUESTS_CNT 列的平均值并列出所有与平均值匹配的行。我该怎么做?我不能在我考虑过的 WHERE 子句中使用 AVG 函数,所以我应该使用 HAVING 吗?

您的查询可以归结为:

SELECT c.gridx, c.gridy, COUNT(*) AS requests_cnt
FROM requests r 
JOIN clients c ON c.id = r.client_id 
GROUP BY c.gridx, c.gridy;

即获取每个 gridx/gridy 的请求计数。您想要确定平均计数,然后仅显示恰好出现频率为 gridx/gridy 的对。在您的示例中,这将是 (2|5)、(-1|-3) 对,但我猜大多数情况下根本就没有对。

最简单的方法似乎是通过应用 AVG OVER:

来获得平均值 on-the-fly
SELECT gridx, gridy
FROM
(
  SELECT 
    c.gridx, c.gridy, COUNT(*) AS requests_cnt,
    AVG(COUNT(*)) OVER () AS avg_requests_cnt
  FROM requests r 
  JOIN clients c ON c.id = r.client_id 
  GROUP BY c.gridx, c.gridy
) pairs
WHERE requests_cnt = avg_requests_cnt
ORDER BY gridx, gridy;