我在Oracle中有一个表,我希望在应用某些条件后获得10%的样本记录。我在谷歌搜索但是我没有得到正确的算法来在Oracle中的WHERE子句之后使用SAMPLE子句。
我用下面的例子解释了我的要求。能否请您建议如何编写SQL查询?我的尝试没有用。
表名:住宿
表格记录:
ACCOM_ID ACCOM_TYPE
-------- ----------
1 HOTEL
2 HOTEL
3 HOTEL
4 HOTEL
5 HOUSE
6 HOUSE
7 CRUISE
在这里,我希望在应用条件后获得50%的样本记录。也就是说,
SELECT * FROM (SELECT * FROM ACCOMMODATION WHERE ACCOM_TYPE = 'HOTEL') T SAMPLE(50);
或
SELECT * FROM (SELECT * FROM ACCOMMODATION WHERE ACCOM_TYPE = 'HOUSE') T SAMPLE(50);
但是上面的查询无效,失败并显示错误ORA-00933: SQL command not properly ended
。如果我使用如下,它没有正确返回给我的结果。我只想要2个随机酒店记录,但它有时会返回2,有时3,有时4。
select * from accommodation sample(50) where accom_type = 'HOTEL';
请参考sql小提琴示例HERE。
编辑:这是示例表。我使用的真实表有很多记录,所以不幸的是我无法order by dbms_random.value()
因为它需要很长时间才能完成。
答案 0 :(得分:1)
这应该可行,但对于一张大桌来说它不会很快:
select * FROM (
select * from accommodation
where accom_type = 'HOTEL'
order by dbms_random.value
)
WHERE rownum <= 0.5 * (
SELECT count(*) FROM accommodation where accom_type = 'HOTEL'
)
;
答案 1 :(得分:1)
这是给定表上的示例代码,用于根据您的需要获取结果。我从每个ACCOM_TYPE获取80%的行。
SELECT *
FROM ( SELECT a.*,
ROW_NUMBER () OVER (PARTITION BY ACCOM_TYPE ORDER BY ACCOM_ID)
AS pos
FROM ACCOMMODATION a
ORDER BY ACCOM_TYPE, pos) t
WHERE pos <= (SELECT ROUND ( (COUNT (*) * 80) / 100)
FROM ACCOMMODATION
WHERE ACCOM_TYPE = t.ACCOM_TYPE)
ORDER BY ACCOM_TYPE, DBMS_RANDOM.VALUE;
在内联视图查询中找出row_number为pos
列别名,然后在主查询过滤器中,基于每个ACCOM_TYPE的总行数的80%(这可以相应地更改)的行。
最后,对于随机结果,按顺序使用DBMS_RANDOM.VALUE
。
希望这有帮助。
答案 2 :(得分:0)
一种方法是计算您对HOTEL和HOUSE的行数,然后使用该数字除以/ 2。此查询将计算HOUSE的行数,并使用从子查询中获得的rownum数
Select * from Accommodation
Where ACCOM_TYPE = 'HOTEL'
and rownum <= (Select count(accom_id)/2 as HotelCount from ACCOMMODATION
WHERE ACCOM_TYPE = 'HOTEL'
group by accom_type)
UNION
Select * from Accommodation
Where ACCOM_TYPE = 'HOUSE'
and rownum <= (Select count(accom_id)/2 as HotelCount from ACCOMMODATION
WHERE ACCOM_TYPE = 'HOUSE'
group by accom_type)