postgresql中是否有类似的函数用于mysql的SQL_CALC_FOUND_ROWS?

时间:2010-07-30 15:59:24

标签: postgresql

每个使用mysql的人都知道:

SELECT SQL_CALC_FOUND_ROWS ..... FROM table WHERE ...  LIMIT 5, 10;

并且在运行之后立即:

SELECT FOUND_ROWS();

我如何在postrgesql中执行此操作?到目前为止,我发现只有两次我必须发送查询...

3 个答案:

答案 0 :(得分:5)

不,没有(至少not as of July 2007)。我担心你不得不诉诸:

BEGIN ISOLATION LEVEL SERIALIZABLE;

SELECT id, username, title, date FROM posts ORDER BY date DESC LIMIT 20;
SELECT count(id, username, title, date) AS total FROM posts;

END;

isolation level需要为SERIALIZABLE,以确保查询不会在SELECT语句之间看到并发更新。

但是,您拥有的另一个选项是使用触发器来计算行INSERTDELETE d。假设您有下表:

CREATE TABLE posts (
    id      SERIAL PRIMARY KEY,
    poster  TEXT,
    title   TEXT,
    time    TIMESTAMPTZ DEFAULT now()
);

INSERT INTO posts (poster, title) VALUES ('Alice',   'Post 1');
INSERT INTO posts (poster, title) VALUES ('Bob',     'Post 2');
INSERT INTO posts (poster, title) VALUES ('Charlie', 'Post 3');

然后,执行以下操作以创建一个名为post_count的表,其中包含posts中行数的运行计数:

-- Don't let any new posts be added while we're setting up the counter.
BEGIN;
LOCK TABLE posts;

-- Create and initialize our post_count table.
SELECT count(*) INTO TABLE post_count FROM posts;

-- Create the trigger function.
CREATE FUNCTION post_added_or_removed() RETURNS TRIGGER AS $$
    BEGIN
        IF TG_OP = 'DELETE' THEN
            UPDATE post_count SET count = count - 1;
        ELSIF TG_OP = 'INSERT' THEN
            UPDATE post_count SET count = count + 1;
        END IF;
        RETURN NULL;
    END;
$$ LANGUAGE plpgsql;

-- Call the trigger function any time a row is inserted.
CREATE TRIGGER post_added_or_removed_tgr
    AFTER INSERT OR DELETE
    ON posts
    FOR EACH ROW
    EXECUTE PROCEDURE post_added_or_removed();

COMMIT;

请注意,这会保留posts所有行的运行计数。要保持某些行的运行计数,您必须调整它:

SELECT count(*) INTO TABLE post_count FROM posts WHERE poster <> 'Bob';

CREATE FUNCTION post_added_or_removed() RETURNS TRIGGER AS $$
    BEGIN
        -- The IF statements are nested because OR does not short circuit.
        IF TG_OP = 'DELETE' THEN
            IF OLD.poster <> 'Bob' THEN
                UPDATE post_count SET count = count - 1;
            END IF;
        ELSIF TG_OP = 'INSERT' THEN
            IF NEW.poster <> 'Bob' THEN
                UPDATE post_count SET count = count + 1;
            END IF;
        END IF;
        RETURN NULL;
    END;
$$ LANGUAGE plpgsql;

答案 1 :(得分:4)

有一种简单的方法,但请记住,COUNT(*)aggr函数之后将应用于在limit / offset之前和之后返回的所有行(可能是costy)

选择     ID,     &#34;计数&#34; (*)OVER()AS cnt 从     对象 哪里     id&gt; 2 OFFSET 50 限制5

答案 2 :(得分:0)

不,当您只需要10个结果时,PostgreSQL不会尝试计算所有相关结果。您需要一个单独的COUNT来计算所有结果。