如何从查询中选择最后x%的行?

时间:2012-11-08 22:52:57

标签: sql sqlite

我想从查询中选择最后一行的1 / x部分,以某种方式排序。我怎么能这样做?

我想出了像

这样的东西
SELECT avg(smilies_count)
FROM posts AS p
WHERE time >= (???) -- I only want the last 25% of posts in this thread
GROUP BY thread_id; -- each thread can have more than 1 post, but I still only
                    -- want to consider the last 25% of posts in my average

但是我不太清楚在???放什么不会导致极其粗糙的表达。

修改

我试过把

SELECT min(p2.time)
FROM posts AS p2
WHERE p2.thread_id = p.thread_id
ORDER BY p2.time DESC
LIMIT count(*) / 4
<{1>}中的

,但它只给了我

???

2 个答案:

答案 0 :(得分:2)

我认为你基本上想要每个帖子中25%的最后帖子,以后的操作由你决定。

如果我是对的,那么这段代码应该适合你(为MS-SQL编写,应该可以轻松地移植到SQLite):

CREATE TABLE posts (
    post_id INT,
    thread_id INT
)

INSERT INTO posts(post_id, thread_id) VALUES (1, 1)
INSERT INTO posts(post_id, thread_id) VALUES (2, 2)
INSERT INTO posts(post_id, thread_id) VALUES (3, 2)
INSERT INTO posts(post_id, thread_id) VALUES (4, 3)
INSERT INTO posts(post_id, thread_id) VALUES (5, 3)
INSERT INTO posts(post_id, thread_id) VALUES (6, 3)
INSERT INTO posts(post_id, thread_id) VALUES (7, 3)
INSERT INTO posts(post_id, thread_id) VALUES (8, 3)
INSERT INTO posts(post_id, thread_id) VALUES (9, 3)
INSERT INTO posts(post_id, thread_id) VALUES (10, 3)
INSERT INTO posts(post_id, thread_id) VALUES (11, 3)

SELECT src.*
FROM (
    SELECT post_number = (
        SELECT 1 + COUNT(*)
        FROM posts pp 
        WHERE p.post_id > pp.post_id 
        AND p.thread_id = pp.thread_id
    ), 
    post_id,
    thread_id
    FROM posts p
) src
JOIN (
    SELECT thread_id, cnt = COUNT(*)
    FROM posts
    GROUP BY thread_id
) counts
ON src.thread_id = counts.thread_id
WHERE (CONVERT(FLOAT, src.post_number) / CONVERT(FLOAT, counts.cnt)) >= 0.75

请注意,它不是高性能查询,主要是因为获得post_number的子查询。对于支持它的DBMS,它可以用更好的方式用OVER子句编写。

答案 1 :(得分:-1)

这是一个版本,如果你需要最后25%的总帖子:

select
  avg(1.0 * smilies_count) avg_count,
from (select top 25% * from posts order by time desc) last_posts

对于每个帖子,最后25%的帖子还有一个:

select
  avg(1.0 * smilies_count) avg_smilies
from (
  select
    thread_id, post_id, smilies_count,
    row_number() over (partition by thread_id order_by time desc) row_num
  from posts
) p
join (select thread_id, count(*) cnt from posts group by thread_id) c on
  p.thread_id = c.thread_id
where
  p.row_num < 0.25 * c.cnt
group by
  p.thread_id