SQL - 保证至少有 n 个唯一用户,每个用户在查询中出现 2 次
SQL - Guarantee at least n unique users with 2 appearances each in query
我正在使用 AWS Personalize,其中一项服务配额是“至少 1000 条记录,至少包含 25 个唯一用户,每个用户至少有 2 个记录”,我知道我的原始数据有这些数字,但是我正在尝试找到一种方法来保证这些数字将始终得到满足,即使将来查询由其他人 运行 也是如此。
简单的方法是只使用完整的数据集,但现在我们正在努力实现 POC,所以这并不是我的第一选择。我已经通过计算出现次数覆盖了“每个记录两个”部分,但我不知道如何保证 25 个用户的最小值。
重要的是要说我的数据在保存时没有以任何方式洗牌。
我的查询
SELECT C.productid AS ITEM_ID,
A.userid AS USER_ID,
A.createdon AS "TIMESTAMP",
B.fromaddress_countryname AS "LOCATION"
FROM A AS orders
JOIN B AS sub_orders ON orders.order_id = sub_orders.order_id
JOIN C AS order_items ON orders.order_id = order_items.order_id
WHERE orders.userid IN (
SELECT orders.userid
FROM A AS ORDERS
GROUP BY orders.userid
HAVING count(*) > 2
)
LIMIT 10
我使用 LIMIT 只查询一个子集,因为我在 AWS Athena 中。
IN
查询效率不高,因为它需要将每一行与子查询的所有(最坏情况)元素进行比较以找到匹配项。
首先将所有至少有 2 条记录的用户存储在一个公共 table 表达式 (CTE) 中,然后与 select 他们进行连接会更容易。
为确保至少有 25 个不同的用户,您需要一个 window 函数来计算自第一行以来的唯一用户数,并在该计数上添加条件。由于您不能在 where
子句中使用 window 函数,因此您将需要第二个 CTE 和查询它的最终查询。
例如:
with users as (
select userid as good_users
from orders
group by 1
having count(*) > 1 -- this condition ensures at least 2 records
),
cte as (
SELECT C.productid AS ITEM_ID,
A.userid AS USER_ID,
A.createdon AS "TIMESTAMP",
B.fromaddress_countryname AS "LOCATION",
count(distinct A.userid) over (rows between unbounded preceding and current row) as n_distinct_users
FROM A AS orders
JOIN B AS sub_orders ON orders.order_id = sub_orders.order_id
JOIN C AS order_items ON orders.order_id = order_items.order_id
JOIN users on A.userid = users.userid --> ensure only users with 2 records
order by A.userid -- needed for the window function
)
select * from cte where n_distinct_users < 26
在 cte
中对 userid
进行排序将确保每个用户 ID 至少有 2 条记录出现在结果中。
我正在使用 AWS Personalize,其中一项服务配额是“至少 1000 条记录,至少包含 25 个唯一用户,每个用户至少有 2 个记录”,我知道我的原始数据有这些数字,但是我正在尝试找到一种方法来保证这些数字将始终得到满足,即使将来查询由其他人 运行 也是如此。
简单的方法是只使用完整的数据集,但现在我们正在努力实现 POC,所以这并不是我的第一选择。我已经通过计算出现次数覆盖了“每个记录两个”部分,但我不知道如何保证 25 个用户的最小值。
重要的是要说我的数据在保存时没有以任何方式洗牌。
我的查询
SELECT C.productid AS ITEM_ID,
A.userid AS USER_ID,
A.createdon AS "TIMESTAMP",
B.fromaddress_countryname AS "LOCATION"
FROM A AS orders
JOIN B AS sub_orders ON orders.order_id = sub_orders.order_id
JOIN C AS order_items ON orders.order_id = order_items.order_id
WHERE orders.userid IN (
SELECT orders.userid
FROM A AS ORDERS
GROUP BY orders.userid
HAVING count(*) > 2
)
LIMIT 10
我使用 LIMIT 只查询一个子集,因为我在 AWS Athena 中。
IN
查询效率不高,因为它需要将每一行与子查询的所有(最坏情况)元素进行比较以找到匹配项。
首先将所有至少有 2 条记录的用户存储在一个公共 table 表达式 (CTE) 中,然后与 select 他们进行连接会更容易。
为确保至少有 25 个不同的用户,您需要一个 window 函数来计算自第一行以来的唯一用户数,并在该计数上添加条件。由于您不能在 where
子句中使用 window 函数,因此您将需要第二个 CTE 和查询它的最终查询。
例如:
with users as (
select userid as good_users
from orders
group by 1
having count(*) > 1 -- this condition ensures at least 2 records
),
cte as (
SELECT C.productid AS ITEM_ID,
A.userid AS USER_ID,
A.createdon AS "TIMESTAMP",
B.fromaddress_countryname AS "LOCATION",
count(distinct A.userid) over (rows between unbounded preceding and current row) as n_distinct_users
FROM A AS orders
JOIN B AS sub_orders ON orders.order_id = sub_orders.order_id
JOIN C AS order_items ON orders.order_id = order_items.order_id
JOIN users on A.userid = users.userid --> ensure only users with 2 records
order by A.userid -- needed for the window function
)
select * from cte where n_distinct_users < 26
在 cte
中对 userid
进行排序将确保每个用户 ID 至少有 2 条记录出现在结果中。