我正在尝试编写一个查询,该查询为系统中的每个日期、每个测试和每个区域扫描一个包含多个状态项的表。目标是在一个给定的区域内获得每个测试的每个日期的最新状态。这将使我能够全面了解系统,以确定大多数测试失败的地方。
下面是基本的表结构,但为了便于使用,我创建了这个SQLFiddle。
CREATE TABLE area (
area_id integer NOT NULL,
area_name character varying(100)
);
CREATE TABLE test (
test_id integer NOT NULL,
test_name character varying(100) NOT NULL,
area_id integer NOT NULL,
test_isvisible boolean DEFAULT true
);
CREATE TABLE status (
status_date bigint NOT NULL,
test_id integer NOT NULL,
process_state_id integer NOT NULL,
process_step_id integer NOT NULL,
status_iteration integer DEFAULT 1 NOT NULL,
status_time bigint NOT NULL
);
CREATE TABLE process_state (
process_state_id integer NOT NULL,
process_state_name character varying(100)
);
CREATE TABLE process_step (
process_step_id integer NOT NULL,
process_step_name character varying(100)
);
我目前拥有的查询获得了对每个可用日期进行一个测试的最远的测试处理点。我想找出一种方法来获取相同类型的信息,而不是传递给定区域的id,这样我就可以为该区域的每个测试获得相同的数据。
也就是说,在SQLFiddle中,在test1的日期为7月2-10日,我还希望查询返回test2的同一组信息,从而返回18行而不是9行。
我遇到的主要问题是,当我试图加入area表并以这种方式获得所有测试时,我只会得到9天的数据,就像我在一个测试中所做的那样,但是只是来自不同测试的数据的混合匹配。
如果你需要更多的信息,请告诉我,如果我能在这里的人之前弄清楚,我会在这里发帖的。
正如注释中指出的那样,编辑,这个试用数据没有键(主键或外键),仅仅是因为它节省了时间,并且对于手头的问题没有必要。但是需要注意的是,在实际应用程序中,这些键是100%必需的,因为数据集越大,对表运行查询就越不守规矩,越费时。
教训:不要吸毒,做钥匙。
发布于 2014-09-09 17:18:06
几个小时后,我找到了一种不同的思考方式,最终得到了我想要的数据。
我意识到,我以前尝试的主要问题是使用GROUP BY,因为如果我将其中任何一列分组,就必须对每一列进行分组。因此,我首先编写了一个查询,它只为我提供了test_id/test_name以及有数据的每个日期,因为我知道我可以对所有这些都进行分组,没有问题:
SELECT t.test_name AS test_name,
to_char( to_timestamp(s.status_date)::TIMESTAMP, 'MM/DD/YYYY' ) AS event_date,
s.status_date
FROM status s
INNER JOIN test t ON t.test_id = s.test_id
INNER JOIN area a ON a.area_id = t.area_id
INNER JOIN process_step step ON s.process_step_id = step.process_step_id
INNER JOIN process_state state ON s.process_state_id = state.process_state_id
WHERE a.area_id = 12
GROUP BY t.test_id, s.status_date, t.test_name;
这并没有给我任何关于测试通过的地方的信息(已经完成,失败,运行)。因此,我编写了一个单独的查询,当它被赋予一个test_id和一个status_date时,它只获得测试状态:
SELECT
CASE WHEN state.process_state_name = 'FAILURE' OR state.process_state_name = 'WAITING' OR state.process_state_name = 'VOLUME' THEN state.process_state_name
WHEN step.process_step_name = 'COMPLETE' AND (state.process_state_name = 'SUCCESS' OR state.process_state_name = 'APPROVED') THEN 'Complete'
ELSE 'Running'
END AS process_state
FROM status s
INNER JOIN process_step step ON s.process_step_id = step.process_step_id
INNER JOIN process_state state ON s.process_state_id = state.process_state_id
WHERE s.test_id = 290
AND s.status_date = 1404273600
AND s.status_iteration = (SELECT MAX(s.status_iteration)
FROM status s
WHERE s.test_id = 290
AND s.status_date = 1404273600)
ORDER BY s.status_time DESC, s.process_step_id DESC, s.process_step_id DESC
LIMIT 1;
因此,这个查询只适用于一个测试和日期,我认为它可以很好地处理原始查询中的子查询,因为它将通过逻辑绕过组。因此,考虑到这一点,我开始合并这两个查询,以获得最后一个查询:
SELECT t.test_name AS test_name,
to_char( to_timestamp(status.status_date)::TIMESTAMP, 'MM/DD/YYYY' ) AS event_date,
(
SELECT
CASE WHEN state.process_state_name = 'FAILURE' OR state.process_state_name = 'WAITING' OR state.process_state_name = 'VOLUME' THEN state.process_state_name
WHEN step.process_step_name = 'COMPLETE' AND (state.process_state_name = 'SUCCESS' OR state.process_state_name = 'APPROVED') THEN 'Complete'
ELSE 'Running'
END AS process_state
FROM status s
INNER JOIN process_step step ON s.process_step_id = step.process_step_id
INNER JOIN process_state state ON s.process_state_id = state.process_state_id
WHERE s.test_id = t.test_id
AND s.status_date = status.status_date
AND s.status_iteration = (SELECT MAX(s.status_iteration)
FROM status s
WHERE s.test_id = t.test_id
AND s.status_date = status.status_date)
ORDER BY s.status_time DESC, s.process_step_id DESC, s.process_step_id DESC
LIMIT 1
) AS process_status
FROM status status
INNER JOIN test t ON t.test_id = status.test_id
INNER JOIN area a ON a.area_id = t.area_id
WHERE a.area_id = 12
GROUP BY t.test_id, status.status_date, t.test_name
ORDER BY 1, 2;
所有这些都可以在我的修正SQLFiddle中看到。如果你对我做了什么有疑问,请告诉我,希望这对未来的开发人员有帮助。
https://stackoverflow.com/questions/25748098
复制相似问题