Выбор двух строк с использованием SQL, где они не сравнивались ранее - PullRequest
1 голос
/ 26 января 2011

У меня есть база данных, в которой пользователям представлены два элемента, и я выбираю лучший из двух.Я только хочу показать пользователям сравнения, которые они еще не сделали.У меня есть две таблицы:

Таблица элементов

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

Таблица голосования

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

Мне нужна) SQL-запрос, который дает пользователю два случайных элемента для сравнения, которые пользователь еще не сравнивал друг с другом.

Ответы [ 2 ]

2 голосов
/ 26 января 2011
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 строку
  • В выбранном, показать идентификатор и имя для обоих элементов

Чтобы отобразить его в виде двух отдельных строк, для этого следует использовать передний конец. Но чтобы сделать это чисто в 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 голос
/ 26 января 2011

Вы можете использовать предложение 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...