Oracle-优化SQL查询

里贾纳·威廉姆森(Regina Williamson)

我有两个表-国家(ID,名称)和用户(ID,名称,country_id)。每个用户都属于一个国家。我想从同一随机国家/地区中选择10个随机用户。但是,有些国家的用户少于10个,因此我无法使用它们。我只需要从那些至少有10个用户的国家中选择。

我可以这样写:

SELECT * FROM(
   SELECT * 
   FROM users u
   {MANY_OTHER_JOINS_AND_CONDITIONS}
   WHERE u.country_id = 
  (
    SELECT * 
    FROM
    (
      SELECT c.id 
      FROM countries c
      JOIN 
      (
        SELECT users.country_id, COUNT(*) as cnt 
        FROM users 
        {MANY_OTHER_JOINS_AND_CONDITIONS}
        GROUP BY users.country_id
      ) X ON X.country_id = c.id 
      WHERE X.cnt >= 10 
      ORDER BY DBMS_RANDOM.RANDOM
    ) Y
    WHERE ROWNUM = 1
  ) 
  ORDER BY DBMS_RANDOM.RANDOM
) Z WHERE ROWNUM < 10

但是,在我的实际情况下,我有更多条件,并加入其他表来确定哪个用户适用。通过使用此查询,我必须在两个地方都具有这些条件-在实际选择数据的查询中和在count子查询中。

有什么办法可以这样写查询,但又不能在两个地方同时满足其他条件(这在性能方面可能不是很好)?

乔尔·科洪

您可以将CTE用于用户条件,以避免重复逻辑并允许DB缓存一次设置的值(尽管根据我的经验,DB并没有达到应有的水平,因此请检查执行计划)。

我比Oracle更像是Sql Server专家,语法略有不同,因此可能需要进行一些调整,但是请尝试以下操作:

WITH SafeUsers (ID, Name, country_id) As
(
   --criteria for users only has to specified here
   SELECT ID, Name, country_id
   FROM users
   WHERE ... 
),
RandomCountry (ID) As 
( 
    SELECT ID 
    FROM (
        SELECT u.country_id AS ID
        FROM SafeUsers u -- but we reference it HERE
        GROUP BY u.country_id
        HAVING COUNT(u.Id) >= 10
        ORDER BY DBMS_RANDOM.RANDOM
    ) c
    WHERE ROWNUM = 1
)
SELECT u.* 
FROM (
    SELECT s.*        
    FROM SafeUsers s -- and HERE
    INNER JOIN RandomCountry r ON s.country_id = r.ID
    ORDER BY DBMS_RANDOM.RANDOM
) u
WHERE ROWNUM <= 10

并且通过删除嵌套并为每个中间步骤引入名称,此查询突然变得易于阅读和维护。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章