#sql #ruby-on-rails #ruby #activerecord
#sql #ruby-on-rails #ruby #activerecord
Вопрос:
Итак, у меня есть Story
и Share
модель. Story
Принадлежит a Share
, а a Share
имеет_one Story
. У них обоих есть временные метки. Share
является самоссылочным, поэтому в нем есть parent_id
столбец, и иногда общий ресурс будет вложен под другим. И это не бесконечно вложимо, всего на один уровень ниже.
Изначально я просто сортировал по created_at
столбцу Story
. Но теперь мне нужно сделать что-то немного более сложное. Если у Story
есть Share
или вложенные общие ресурсы, я бы хотел также выполнить сортировку по created_at
столбцам из них. Идея заключается в том, что дальнейшая активность с этим Story
(вложенные ресурсы) поднимет его на вершину порядка.
РЕДАКТИРОВАТЬ: Вот решение:
SELECT * FROM stories
LEFT OUTER JOIN shares AS s1 ON stories.share_id = s1.id
LEFT OUTER JOIN shares AS s2 ON s2.parent_id = s1.id
ORDERY BY s2.created_at DESC NULLS LAST, stories.created_at DESC
Или в ActiveRecord:
Story.joins('LEFT OUTER JOIN shares AS s1 ON stories.share_id = s1.id').
joins('LEFT OUTER JOIN shares AS s2 ON s2.parent_id = s1.id').
order('s2.created_at DESC NULLS LAST, stories.created_at DESC')
Спасибо за помощь!
Комментарии:
1. Возможно, вы захотите добавить некоторые тестовые данные и ожидаемые результаты.
Ответ №1:
Вам придется дважды присоединяться к Share. В SQL это было бы что-то вроде этого:
select * from stories
left outer join shares as s1 on s1.story_id=stories.id
left outer join shares as s2 on s1.parent_id=s2.id
order by greatest(s2.updated_at,s1.updated_at,stories.updated_at)
Не знаю, как это сделать в Rails, попробуйте поэкспериментировать с:включает
Комментарии:
1. Ах, очень интересно. Хорошо, итак, внешний ключ на самом деле находится в Story, а не в Share. Итак, в Story есть столбец share_id. Я переключил его, и с одним соединением, похоже, все работает нормально, однако второе соединение, похоже, работает неправильно. В консоли postgres после первого объединения я вижу столбцы истории с добавленными (присоединенными) после них столбцами общего доступа. Но когда я выполняю второе объединение, добавляется второй набор столбцов общего доступа, но все они пусты. Я собираюсь отредактировать исходное сообщение, чтобы показать, что у меня есть на данный момент.
2. О, подождите. Разве это не должно быть
s1.id = s2.parent_id
? Hrm, столбцы второго соединения по-прежнему пусты.3. О, неважно, это действительно работает. Я только недавно очистил вложенный общий ресурс, поэтому внизу был только один, и я пропустил его. Спасибо!
4. Хорошо. Последняя часть; упорядочивание. Я начал только с вложенных
created_at
, так что это было быs2.created_at
. Если я это сделаюs2.created_at DESC
, две строки со значениями дляs2.created_at
будут в правильном порядке, но они полностью внизу. Это помещает строки, которые имеютnulls
для этого поля, перед строками с фактическими значениями. Как предотвратить это?5. Хорошо, разобрался. В Postgres есть возможность переключать порядок сортировки нулей. По умолчанию это
NULLS FIRST
, поэтому просто измените его наNULLS LAST
. Решение выше.