【问题标题】:Writing subqueries in SQL在 SQL 中编写子查询
【发布时间】:2017-05-26 10:37:13
【问题描述】:

我正在学习 PostgreSQL,并且我有一个包含以下列的数据库日志:路径文本、ip inet、方法文本、状态文本、时间时间戳记、id int

使用此数据库,我的目标是找到错误百分比(状态!= '200 OK' / 状态)超过 2.5% 的任何日子。我有如下查询,它以小数形式得到错误百分比,但我不知道如何将它们乘以 10 以使它们成为“百分比”,也不知道如何检查它们是否超过 2.5。

我已经在多个地方同时尝试了 HAVING 和 WHERE,但是无论我在哪里输入 HAVING 或 WHERE,我都会在 group by 处遇到编程错误或语法错误。将其更改为百分比并检查其是否超过 2.5 的正确方法是什么?提前致谢

模拟数据:

CREATE TABLE log (
    path text,
    ip inet,
    method text,
    status text,
    "time" timestamp with time zone DEFAULT now(),
    id integer NOT NULL
);

INSERT INTO log VALUES ('/article/bears-love-berries', '198.51.100.76' , 'GET', '200 OK', '2016-07-1 12:54:22+00', 3355597);
INSERT INTO log VALUES ('/article/candidate-is-jerk', '198.51.100.76' , 'GET', '200 OK', '2016-07-1 19:54:22+00', 3355598);
INSERT INTO log VALUES ('/article/bears-love-berries', '198.51.100.76' , 'GET', '404 NOT FOUND', '2016-07-1 22:54:22+00', 3355599);
INSERT INTO log VALUES ('/article/goats-eat-googles', '203.0.113.42' , 'GET', '200 OK', '2016-07-11 12:54:22+00', 3355600);
INSERT INTO log VALUES ('/article/candidate-is-jerk', '203.0.113.42' , 'GET', '200 OK', '2016-07-11 17:54:22+00', 3355601);
INSERT INTO log VALUES ('/article/bears-love-berries', '203.0.113.42' , 'GET', '200 OK', '2016-07-11 19:54:22+00', 3355602);
INSERT INTO log VALUES ('/article/goats-eat-googles', '203.0.113.42' , 'GET', '404 NOT FOUND', '2016-07-15 13:54:22+00', 3355603);
INSERT INTO log VALUES ('/article/bears-love-berries', '198.51.100.34' , 'GET', '200 OK', '2016-07-15 20:54:22+00', 3355604);
INSERT INTO log VALUES ('/article/candidate-is-jerk', '198.51.100.34' , 'GET', '200 OK', '2016-07-15 23:54:22+00', 3355605);
INSERT INTO log VALUES ('/article/candidate-is-jerk', '203.0.113.12' , 'GET', '200 OK', '2016-07-21 19:54:22+00', 3355606);
INSERT INTO log VALUES ('/article/bears-love-berries', '203.0.113.12' , 'GET', '200 OK', '2016-07-21 12:54:22+00', 3355607);
INSERT INTO log VALUES ('/article/goats-eat-googles', '198.51.100.76' , 'GET', '200 OK', '2016-07-21 01:54:22+00', 3355608);
INSERT INTO log VALUES ('/article/goats-eat-googles', '198.51.100.76' , 'GET', '404 NOT FOUND', '2016-07-29 07:54:22+00', 3355609);
INSERT INTO log VALUES ('/article/candidate-is-jerk', '198.51.100.76' , 'GET', '404 NOT FOUND', '2016-07-29 20:54:22+00', 3355610);
INSERT INTO log VALUES ('/article/goats-eat-googles', '198.51.100.34' , 'GET', '200 OK', '2016-07-29 19:54:22+00', 3355611);

查询:

SELECT DATE(time) AS day,
(
  (SELECT CAST(COUNT(status) AS FLOAT)
  FROM log WHERE status != '200 OK') /
  (SELECT CAST(COUNT(status) AS FLOAT))
) AS views
FROM log GROUP BY day
ORDER BY views

【问题讨论】:

  • 把问题分解成更小的问题。什么是百分比?这是两个数字的比率。这两个数字是多少?你需要一个 count status = 200 和一个 count of status != 200。我认为如果你能计算每天的错误,你会发现剩下的很容易。
  • @Brandon 我可以找到状态计数!= 200 和每天的总体请求计数。问题是我如何测试两者的比率是否大于 2.5%,在外部 SELECT 上放置 WHERE 或 HAVING 它有语法错误或未找到列视图错误

标签: postgresql subquery


【解决方案1】:

在 sqlfiddle 中分享了一个测试用例后,我们可以着手编写一个可以运行的代码。

小提琴在这里:http://sqlfiddle.com/#!15/b3ed9/39

您可以只检查已经乘以 0.025 的结果,而不是将结果乘以 100,不是吗?我的意思是,如果您的值介于 0-1 之间,则相当于 2.5% 的值将仅为 0.025。

因此该命令应该这样做:

select views.day, views.cnt from
 (select datelog.day,
  (
   cast(count(case when datelog.status != '200 OK' then 1 else null end) as float)
   /
   cast(count(*) as float)
  ) as cnt
  from (select DATE(time) as day, status from log) as datelog
  group by datelog.day
 ) as views
 where views.cnt > 0.025

最后的修改深深植根于这里的回复:SQL use column from subselect in where clause

【讨论】:

  • 我试过这个和 HAVING 但我得到 ProgrammingError: Column 'views' does not exist?另外,我试图让它成为 2.5 而不是 0.025 的原因是我需要将它呈现给 python 来显示它,而不必在 python 中更新 100 倍。
  • 当我做 HAVING 而不是我在 GROUP BY 上得到语法错误而不是列错误时
  • 你不认为你错过了你的两个子选择的括号吗?我的意思是,我阅读了 / () AS 视图 - 所以 ( / ) AS 视图不应该这样做?
  • 糟糕,我不小心打错了帖子,但不,它仍然给出视图不存在错误
  • 您的第二个子查询也缺少“FROM log”。 :)
猜你喜欢
  • 2020-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多