You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求符合全员亲属/俱乐部成员关系的最高参与人数套餐SQL查询

解决日套餐参与者关系筛选与人数统计的SQL问题

现有数据表

1. RELATED表(用户关系记录表)

字段包含 Person1_UID、Person2_UID、Type,数据如下:

Person1_UID Person2_UID   Type
1           2             club member
1           9             family
1           11            colleague
2           4             friend
2           7             colleague
3           4             club member
3           6             colleague
3           9             friend
3           10            follower
4           6             family
4           10            family
5           8             family
6           11            colleague
7           8             colleague
8           11            friend

2. DAY_PACKAGE表(日套餐参与信息表)

字段包含 DID(日套餐ID)、Description(套餐描述)、UID(用户ID)、VID(优惠券ID),数据如下:

DID Description    UID  VID
1   Spa Day         1   19
1   Spa Day         2   20
1   Spa Day         9   17
2   Adventure Time  4   16
2   Adventure Time  6   16
3   Family Fun Day  3   18
3   Family Fun Day  4   17
3   Family Fun Day  7   18
3   Family Fun Day  10  19
4   Relaxation Date 5   20

需求说明

编写SQL查询,找出所有参与者彼此之间均为family(亲属)或club member(俱乐部成员)关系的日套餐中,参与人数最多的那些。查询需返回 DID、Description、Participant_Count 三个字段,期望结果如下:

DID Description Participant_Count
1   Spa Day         3
2   Adventure Time  2  

用户当前已写出统计各套餐总参与人数的基础SQL:

SELECT Description, COUNT(DISTINCT UID) AS Participants_Count
FROM DAY_PACKAGE
GROUP BY Description
ORDER BY Participants_Count DESC

解决方案

要实现需求,需分步骤筛选符合条件的套餐:

第一步:生成每个套餐内的所有用户配对

通过自连接DAY_PACKAGE表,得到每个套餐下所有两两不同用户的组合(排除用户自身配对):

SELECT 
    dp1.DID,
    dp1.UID AS UID1,
    dp2.UID AS UID2
FROM DAY_PACKAGE dp1
JOIN DAY_PACKAGE dp2 
    ON dp1.DID = dp2.DID 
    AND dp1.UID < dp2.UID

第二步:验证用户对的关系是否符合要求

由于用户关系是双向的(比如A和B的关系可能存为Person1_UID=A,Person2_UID=B或反过来),关联RELATED表时需匹配两种情况,筛选出关系为family或club member的有效配对:

SELECT 
    dp_pair.DID,
    COUNT(*) AS valid_pairs,
    (SELECT COUNT(DISTINCT UID) FROM DAY_PACKAGE dp WHERE dp.DID = dp_pair.DID) AS Participant_Count
FROM (
    SELECT 
        dp1.DID,
        dp1.UID AS UID1,
        dp2.UID AS UID2
    FROM DAY_PACKAGE dp1
    JOIN DAY_PACKAGE dp2 
        ON dp1.DID = dp2.DID 
        AND dp1.UID < dp2.UID
) dp_pair
LEFT JOIN RELATED r 
    ON (dp_pair.UID1 = r.Person1_UID AND dp_pair.UID2 = r.Person2_UID) 
    OR (dp_pair.UID1 = r.Person2_UID AND dp_pair.UID2 = r.Person1_UID)
WHERE r.Type IN ('family', 'club member')
GROUP BY dp_pair.DID

第三步:筛选全符合关系要求且人数最多的套餐

一个有n个参与者的套餐,总共有n*(n-1)/2个用户对。只有当有效配对数等于总配对数时,说明该套餐所有参与者彼此关系都符合要求。结合人数排序,最终SQL如下:

支持QUALIFY子句的数据库(如BigQuery、Snowflake)

WITH package_pairs AS (
    -- 生成每个套餐的所有用户配对
    SELECT 
        dp1.DID,
        dp1.UID AS UID1,
        dp2.UID AS UID2
    FROM DAY_PACKAGE dp1
    JOIN DAY_PACKAGE dp2 
        ON dp1.DID = dp2.DID 
        AND dp1.UID < dp2.UID
),
package_valid_pairs AS (
    -- 统计每个套餐的有效配对数
    SELECT 
        pp.DID,
        COUNT(r.Type) AS valid_pair_count
    FROM package_pairs pp
    LEFT JOIN RELATED r 
        ON (pp.UID1 = r.Person1_UID AND pp.UID2 = r.Person2_UID) 
        OR (pp.UID1 = r.Person2_UID AND pp.UID2 = r.Person1_UID)
    WHERE r.Type IN ('family', 'club member')
    GROUP BY pp.DID
),
package_participant_count AS (
    -- 统计每个套餐的参与人数
    SELECT 
        DID,
        COUNT(DISTINCT UID) AS Participant_Count
    FROM DAY_PACKAGE
    GROUP BY DID
)
SELECT 
    ppc.DID,
    dp.Description,
    ppc.Participant_Count
FROM package_participant_count ppc
JOIN package_valid_pairs pvp 
    ON ppc.DID = pvp.DID
JOIN DAY_PACKAGE dp 
    ON ppc.DID = dp.DID
-- 验证有效配对数等于总配对数
WHERE pvp.valid_pair_count = (ppc.Participant_Count * (ppc.Participant_Count - 1)) / 2
-- 筛选参与人数最多的套餐
QUALIFY RANK() OVER (ORDER BY ppc.Participant_Count DESC) = 1
GROUP BY ppc.DID, dp.Description, ppc.Participant_Count
ORDER BY ppc.Participant_Count DESC;

不支持QUALIFY子句的数据库(如MySQL)

WITH package_pairs AS (
    SELECT 
        dp1.DID,
        dp1.UID AS UID1,
        dp2.UID AS UID2
    FROM DAY_PACKAGE dp1
    JOIN DAY_PACKAGE dp2 
        ON dp1.DID = dp2.DID 
        AND dp1.UID < dp2.UID
),
package_valid_pairs AS (
    SELECT 
        pp.DID,
        COUNT(r.Type) AS valid_pair_count
    FROM package_pairs pp
    LEFT JOIN RELATED r 
        ON (pp.UID1 = r.Person1_UID AND pp.UID2 = r.Person2_UID) 
        OR (pp.UID1 = r.Person2_UID AND pp.UID2 = r.Person1_UID)
    WHERE r.Type IN ('family', 'club member')
    GROUP BY pp.DID
),
package_participant_count AS (
    SELECT 
        DID,
        COUNT(DISTINCT UID) AS Participant_Count
    FROM DAY_PACKAGE
    GROUP BY DID
),
valid_packages AS (
    SELECT 
        ppc.DID,
        dp.Description,
        ppc.Participant_Count
    FROM package_participant_count ppc
    JOIN package_valid_pairs pvp 
        ON ppc.DID = pvp.DID
    JOIN DAY_PACKAGE dp 
        ON ppc.DID = dp.DID
    WHERE pvp.valid_pair_count = (ppc.Participant_Count * (ppc.Participant_Count - 1)) / 2
)
SELECT DID, Description, Participant_Count
FROM valid_packages
WHERE Participant_Count = (SELECT MAX(Participant_Count) FROM valid_packages)
ORDER BY Participant_Count DESC;

内容的提问来源于stack exchange,提问作者George Lai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 21:59:59