我有一个包含 2 个引用 (user_id
和item_id
) 的表,我需要查询它以查找具有某些项目的所有用户。棘手的部分是,我需要对结果进行排序,而不仅仅是他们拥有的结果数量,而是基于他们拥有的哪些项目。
这是表格:
+--------------+-----------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-----------------------+------+-----+---------+-------+
| user_id | int(11) | NO | | 0 | |
| item_id | int(11) unsigned | YES | | NULL | |
+--------------+-----------------------+------+-----+---------+-------+
所以我的查询看起来像这样:
SELECT user_id, item_id
FROM user_items
WHERE item_id IN (2, 122, 132)
GROUP BY user_id, item_id
HAVING SUM(item_id = 2);
看起来很容易?这就是困难的部分所在:
item_id = 2 是必需的 item_id = 122 和 132 是可选的。132 之后的任何内容也是可选的。
我需要根据以下条件订购结果:1)如果找到所有项目。2) 如果仅找到第 2 项和第 122 项。3) 如果只找到第 2 项。
这是用于摆弄的 SQL 小提琴文件:http ://sqlfiddle.com/#!2/6b1c1/6/0
我在想,如果有什么方法可以设置,比如:SELECT query to say
IF (item_id = 2 AND item_id = 122 AND item_id = 132) AS matches_all,
IF (item_id = 2, item_id = 122) AS matches_some,
IF (item_id = 2) AS matches_first
使用更新的查询进行编辑 这是我到目前为止所拥有的。这大约是我需要的 95%: http ://sqlfiddle.com/#!2/6b1c1/47
SELECT user_id, item_id,
@tmp_1 := IF(SUM(item_id = 2), 1, 0) AS tmp_1,
@tmp_2 := IF(SUM(item_id = 122), 1, 0) AS tmp_2,
@tmp_3 := IF(SUM(item_id = 132), 1, 0) AS tmp_3,
@tmp_4 := IF(SUM(item_id = 126), 1, 0) AS tmp_4,
CAST(@tmp_3 + @tmp_4 AS UNSIGNED) AS total_other
FROM user_items
WHERE item_id IN (2, 122, 132, 126)
GROUP BY user_id
HAVING SUM(item_id = 2)
ORDER BY tmp_1 DESC, tmp_2 DESC, total_other DESC
更多细节:
1) 我最多只能输入 12 个项目,因此如果需要,我可以为每个项目分配它自己的临时字段。
2) 上述查询对 tmp_1 和 tmp_2 非常有效。如果我们有一个用户拥有项目 2 和 122,它会将它们放在列表的顶部。对于其余的 3-4(3 到最多 12),我需要计算匹配数,这就是我尝试CAST(@tmp_3 + @tmp_4
. 我不知道如何让那些计算。
3) 一旦我对第 3 - 12 项进行了总计算,那么这将是该ORDER BY
条款中的第三项也是最后一项。
示例结果
基于 SQL fiddle 文件中提供的架构,以下是搜索所有具有 item_id 的用户时应返回的结果:2, 122, 132, 126
+---------+--------------+----------------+-------------+
| USER_ID | PRIMARY_ITEM | SECONDARY_ITEM | OTHER_ITEMS |
+---------+--------------+----------------+-------------+
| 39 | 1 | 1 | 2 |
| 54 | 1 | 1 | 0 |
| 55 | 1 | 0 | 0 |
+---------+--------------+----------------+-------------+