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 条记录出现在结果中。