让子查询运行N次

时间:2014-09-09 15:10:43

标签: sql postgresql

我正在尝试编写一个查询,该查询针对系统中的每个区域,针对每个测试扫描具有多个状态条目的表。目标是在一个给定区域内获得每个测试的每个日期的最新状态。这将使我能够对系统进行广泛的概述,以确定大多数测试失败的地方

下面是基本的表格结构,但为了便于使用,我创建了this 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中,我在7月2日至10日期间获得了test1的日期信息,我还希望查询返回test2的相同信息集,从而返回18行而不是9行。

我遇到的主要问题是,当我尝试加入区域表并以这种方式获得所有测试时,我最终只获得了9天的数据,就像我在一次测试中所做的那样,但只是混合 - 来自不同测试的数据匹配。

如果您需要更多信息,请告诉我,如果我能在此之前找到相关信息,我会在此发回。

修改 正如评论中指出的那样,这个试验数据没有密钥(主要或国外),仅仅因为它节省了时间,而且对于手头的问题不是必需的。但值得注意的是,这些密钥在实际应用程序中是100%必需的,因为数据集越大,对表运行查询就会越不规范和耗时。

课程:不要吸毒,做钥匙。

1 个答案:

答案 0 :(得分:1)

经过几个小时后,我发现了一种不同的思考方式,最后得到了我想要的数据。

我意识到我之前尝试的主要问题是使用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;

因此,这个查询适用于单个测试和日期,我认为这对于原始查询中的子查询非常有效,因为它会绕过GROUP BY逻辑。因此,考虑到这一点,我继续合并这两个查询以获得最后一个查询:

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;

所有这一切都可以在我的revised SQLFiddle中看到。 如果您对我所做的事情有疑问,请告诉我,希望这有助于未来的开发人员。