【问题标题】:Sample Clause after Where condition in OracleOracle 中 Where 条件后的示例子句
【发布时间】:2017-07-24 20:41:59
【问题描述】:

我在 Oracle 中有一个表,我想在应用某些条件后获得 10% 的样本记录。我在 Google 中进行了搜索,但我没有得到正确的算法来在 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 fiddle 示例HERE

编辑:这是示例表。我使用的真实表有很多记录,所以很遗憾我无法order by dbms_random.value(),因为它需要很长时间才能完成。

【问题讨论】:

  • 如果我理解您的要求;您想以任何方式随机获取 50% 的记录吗?如果您有 6 条记录,您希望随机显示 3 条记录吗?
  • 我想要 50% 的记录在应用条件之后。例如:50% 的酒店住宿,50% 的住宿。

标签: sql oracle oracle11g


【解决方案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;

在内联视图查询中找出行号为pos 列别名,然后在主查询中根据每个 ACCOM_TYPE 总行数的 80%(您可以相应地更改)过滤行。

最后对于随机结果使用DBMS_RANDOM.VALUE in order by 子句。

希望这会有所帮助。

【讨论】:

  • dbms_random.value 的顺序问题是,查询加载了很长时间。我上面给出的是样本表。我查询的表有很多记录。我必须在应用一些条件后查询随机记录。如果我按 dbms_random.value 使用 order,则查询运行时间很长。如果我使用 sample() 那么它不会返回我需要的东西。
【解决方案2】:

这应该可以,但对于大桌子来说不会很快:

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'
)
;

演示:http://sqlfiddle.com/#!4/6bf8b/13

【讨论】:

  • dbms_random.value 的顺序问题是,查询加载了很长时间。我上面给出的是样本表。我查询的表有很多记录...
  • 如果你删除order by random,查询会很快,但不会给出随机样本。
  • 是的,这正是我面临的问题。应用一些条件后,我必须查询随机记录。如果我按 dbms_random.value 使用 order,则查询运行时间很长。如果我使用 sample() 那么它不会返回我需要的东西。
  • 这张表有主键吗?
【解决方案3】:

一种方法是计算 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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-15
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多