我想选择前1%的行;但是,我不能使用子查询来做到这一点。即,这不会起作用:
SELECT * FROM mytbl
WHERE var='value'
ORDER BY id,random()
LIMIT(SELECT (COUNT(*) * 0.01)::integer FROM mytbl)
如果不使用带有限制的子查询,我将如何完成相同的输出?
答案 0 :(得分:1)
您可以使用PERCENT_RANK
:
WITH cte(ID, var, pc) AS
(
SELECT ID, var, PERCENT_RANK() OVER (ORDER BY random()) AS pc
FROM mytbl
WHERE var = 'value'
)
SELECT *
FROM cte
WHERE pc <= 0.01
ORDER BY id;
的 SqlFiddleDemo
强>
答案 1 :(得分:0)
我使用psycopg2
包解决了它:
cur.execute("SELECT ROUND(COUNT(id)*0.01,0)
FROM mytbl")
nrows = str([int(d[0]) for d in cur.fetchall()][0])
cur.execute("SELECT *
FROM mytbl
WHERE var='value'
ORDER BY id, random() LIMIT (%s)",nrows)
也许有一个更优雅的解决方案只使用SQL,或者更有效的解决方案,但这正是我正在寻找的。 p>
答案 2 :(得分:0)
如果我做对了,你需要:
id
,则所有具有相同id
的行也必须在那里。以下的sql应该可以解决这个问题:
with ids as (
select id,
total,
sum(cnt) over (order by max(rnd)) running_total
from (
select id,
count(*) over (partition by id) cnt,
count(*) over () total,
row_number() over(order by random()) rnd
from mytbl
) q
group by id,
cnt,
total
)
select mytbl.*
from mytbl,
ids
where mytbl.id = ids.id
and ids.running_total <= ids.total * 0.01
order by mytbl.id;
答案 3 :(得分:0)
我当然没有您的数据,但是在LIMIT
子句中使用子查询没有问题。
但是,子查询仅包含count(*)
部分,然后我将结果乘以0.01
:
SELECT * FROM mytbl
WHERE var='value'
ORDER BY id,random()
LIMIT(SELECT count(*) FROM mytbl)*0.01;