使用SQL选择两行,之前尚未进行过比较

时间:2011-01-26 11:40:06

标签: sql mysql comparison

我有一个数据库,用户可以看到两个项目,并选择两者中较好的一个。我只想向用户展示他们尚未做过的比较。我有两张桌子:

项目表

+--------+---------+
| itemId |  name   |
+--------+---------+
|   1    | Dog     |
|   2    | Cat     |
|   3    | Fish    |
|   4    | Rat     |
+--------+---------+

投票表

+--------+--------------+--------------+--------+
| voteId | betterItemId |  worseItemId | userId |
+--------+--------------+--------------+--------+
|    1   |       1      |       2      |    1   |
+--------+--------------+--------------+--------+
|    1   |       1      |       3      |    1   |
+--------+--------------+--------------+--------+

我需要一个(我的)SQL查询,它为我提供了两个随机项供用户进行比较,用户尚未相互比较。

2 个答案:

答案 0 :(得分:2)

select a.itemId, a.name, b.itemId otherItemId, b.name othername
from item a
inner join item b on a.itemId < b.itemId
where not exists (
  select * from vote v
  where ((v.betterItemId = a.itemId and v.worseItemId = b.itemId)
     or  (v.betterItemId = b.itemId and v.worseItemId = a.itemId))
    and v.userId = 1234)   # << enter the userId here
order by rand()
limit 1;
  • 首先生成所有a-b组合,但使用a.id<b.id来防止重复(例如1-2和2-1)。
  • 接下来针对a-b的每个组合,检查(在更好或更差的任何排列中)项目尚未被userId投票(查询中1234的示例)
  • 使用order by rand()
  • 随机排序所有结果
  • 使用limit 1只获得1行
  • 在选择中,显示两个项目的ID和名称

要将其显示为两个单独的行,应使用前端。但要纯粹在MySQL中执行此操作,需要一个技巧。以下内容在撰写本文时尚未经过测试。

select ItemId, name
from
(
    select a.itemId, a.name, @b := b.itemId
    from item a
    inner join item b on a.itemId < b.itemId
    where not exists (
      select * from vote v
      where ((v.betterItemId = a.itemId and v.worseItemId = b.itemId)
         or  (v.betterItemId = b.itemId and v.worseItemId = a.itemId))
        and v.userId = 1234)   # << enter the userId here
    order by rand()
    limit 1
) c
union all
select itemId, name
from item d on d.itemId = @b

答案 1 :(得分:1)

您可以使用not exists子句确保未对该组合进行投票:

select  a.itemId
,       b.itemId
from    Items a
join    Items b
on      a.ItemId < b.ItemId
where   not exists
        (
        select  *
        from    Vote
        where   userId = 42
                and ((betterItemId = a.ItemId and worseItemId = b.ItemId)
                     or (worseItemId = a.ItemId and betterItemId = b.ItemId))
        )
order by
        rand()
limit   2