2016-06-06 3 views
0
items(id) 
user_items(id, user_id, item_id, status) 

У меня есть таблица items с has_many отношений с user_items. Я хотел бы отсортировать по «топ-позициям», где элементы в верхней части списка имеют самое большее user_items с status из 1 (одобрено).Сортировать элементы, основанные на результатах, которые могут или не могут быть в таблице соединение в рельсах

SQL-запрос, который я придумал, кажется немного некрасиво, но, кажется, главным образом сделать работу:

SELECT items.* FROM items LEFT OUTER JOIN user_items ON user_items.item_id = items.id 
     GROUP BY items.id, user_items.status 
     ORDER BY (user_items.status = #{UserItem.statuses[:approved]}) DESC NULLS LAST, 
      COUNT(items.id) DESC 

Проблема с этим состоит в том, что я получаю повторяющиеся элементы в результатах, поэтому я должен опубликовать процесс с чем-то вроде этого: Item.find_by_sql(sql).uniq{|item| item.id}

Как я могу избежать вызова uniq здесь? Есть ли более эффективный запрос, который я мог бы написать, чтобы выполнить одно и то же? И есть ли более чистый способ написать это в Rails, где мне не нужно использовать find_by_sql?

ответ

1

Если вы хотите деталей с самым user_items, то я бы рекомендовал запрос так:

select i.*, 
     (select count(*) 
     from user_items ui 
     where ui.item_id = i.it and ui.status = 1 
     ) as numusers 
from items i 
order by numusers desc; 

Вы может сделать это с left join и group by, а также:

SELECT i.* 
FROM items i LEFT OUTER JOIN 
    user_items ui 
    ON ui.item_id = i.id AND ui.status = 1 
GROUP BY i.id 
ORDER BY COUNT(u.user_id) DESC; 
+0

Улучшит , благодаря! – bos37

+0

Это хорошо работает, но что, если я хочу сортировать ссылки по 'user_items.updated_at'? – bos37

+0

@ bos37. , , Это не имеет смысла. Там может быть более одного матча. Вы можете добавить что-то вроде 'order by min (ui.updated_at)' в предложение 'order by'. –

Смежные вопросы