我希望得到用户(alpha)和他所有朋友之间的头部结果。
users
+--------+-------+
| userID | name |
+--------+-------+
| 1 | alpha |
| 2 | beta |
| 3 | gamma |
| 4 | delta |
+--------+-------+
relationships
+--------------+--------------+------------+
| user1_userID | user2_userID | friendship |
+--------------+--------------+------------+
| 1 | 2 | 1 |
| 1 | 3 | 1 |
| 1 | 4 | 0 |
+--------------+--------------+------------+
games
+-------+-------+--------------------+--------------------+
| user1 | user2 | dollar_share_user1 | dollar_share_user2 |
+-------+-------+--------------------+--------------------+
| 1 | 2 | 50 | 350 |
| 3 | 1 | 100 | 200 |
| 1 | 3 | 150 | 150 |
| 3 | 1 | 100 | 300 |
+-------+-------+--------------------+--------------------+
ratings
+-------+-------+--------+
| user1 | user2 | rating |
+-------+-------+--------+
| 1 | 2 | 4 |
| 2 | 1 | 6 |
| 1 | 3 | 2 |
| 3 | 1 | 1 |
| 1 | 3 | 5 |
| 3 | 1 | 4 |
+-------+-------+--------+
我需要输出
output
+-----------------+---------------+--------------------+--------------+
| opponent_userID | opponent_name | delta_dollar_share | delta_ratings |
+-----------------+---------------+--------------------+--------------+
| 2 | beta | -300 | -2 |
| 3 | gamma | 300 | 2 |
+-----------------+---------------+--------------------+--------------+
where delta_dollar_share for
- beta: 50 - 350 = 300
- gamma: (200+150+300) - (100+150+100) = 650 - 350 = 300
where delta_rating for
- beta: 4 - 6 = -2
- gamma: (2+5) - (1+4) = 2
我已经能够解决(有足够的困难)输出的各个组件。但我只是无法将它们全部合并到一个查询中。
-- get opponents
SELECT u1.userID, u1.name
FROM relationships r
JOIN users u1
ON (r.user2_userID = u1.userID)
WHERE (r.user1_userID = 1) AND (friendship = 1);
-- get delta_dollar_share for one opponent(gamma)
SELECT
(CASE
WHEN (user1 = 1) THEN SUM(dollar_share_user1)
WHEN (user2 = 1) THEN SUM(dollar_share_user2)
END) -
(CASE
WHEN (user1 = 3) THEN SUM(dollar_share_user1)
WHEN (user2 = 3) THEN SUM(dollar_share_user2)
END)
AS delta_dollar_share
FROM games
WHERE
((user1 = 1) AND (user2 = 3)) OR
((user1 = 3) AND (user2 = 1));
-- get delta_ratings for one opponent(gamma)
SELECT
SUM(CASE WHEN (user1 = 1) THEN rating END) -
SUM(CASE WHEN (user1 = 3) THEN rating END) AS delta_ratings
FROM ratings
WHERE
((user1 = 1) AND (user2 = 3)) OR
((user1 = 3) AND (user2 = 1));
请帮助我如何将所有这些组合成一个查询以获得所有对手所需的输出? SQL Fiddle here
答案 0 :(得分:2)
我相信这就是你想要的。我已将您的第二和第三个查询与第一个查询相关联。我还将表达式更改为使用单个和来切换值的符号。
SELECT
u.userID, u.name,
(
SELECT
SUM(
(gm.dollar_share_user1 - gm.dollar_share_user2) *
CASE when gm.user1 = r.user1_userID then 1 else -1 end
)
FROM games gm
WHERE
gm.user1 = r.user1_userID AND gm.user2 = r.user2_userID
OR gm.user1 = r.user2_userID AND gm.user2 = r.user1_userID
) AS delta_dollar_share,
(
SELECT
SUM(rating * CASE when rt.user1 = r.user1_userID then 1 else -1 end)
FROM ratings rt
WHERE
rt.user1 = r.user1_userID AND rt.user2 = r.user2_userID
OR rt.user1 = r.user2_userID AND rt.user2 = r.user1_userID
) AS delta_ratings
FROM
relationships r INNER JOIN users u
ON r.user2_userID = u.userID
WHERE
r.user1_userID = ? AND r.friendship = 1; /* ? = 1 in your example */
工作样本:http://sqlfiddle.com/#!9/8fd7b/16
您实际上只是总结所有美元份额和评级值,只是当用户ID对应于用户1而其他用户的值被扣除时,您将其计为正数。因此,对于美元份额,其中一个总是正数而另一个是负数,这就是为什么它在括号内的差异操作。最终它仍然是全部添加,所以单个sum()
就足够了,但你只需要根据case
表达式的结果翻转符号。
我将额外的计算作为与r.user1_userID
和r.user2_userID
与外部查询相关联(相关)的子查询插入。