我有两个表-国家(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] 删除。
我来说两句