Сохранить порядок из подзапроса IN - PullRequest
2 голосов
/ 05 октября 2011

это должно быть легко, но я не могу заставить MySQL играть в мяч.

Я пытаюсь составить список проектов, за которые проголосовал последний пользователь, для использования на странице профиля этого пользователя.

У меня есть таблица голосов, содержащая uid (INT), проект (INT), отметку времени (INT)

И таблица проектов, чье поле идентификатора совпадает с полем проекта в таблице голосов.

Мой начальный запрос был

SELECT * FROM projects WHERE id IN(SELECT project FROM votes WHERE uid=x ORDER BY timestamp DESC);

Это дает правильный список, но порядок перепутан. Я также понял, что забыл добавить проект DISTINCT в подзапрос, но по какой-то причине он давал разные проекты.

SELECT project FROM votes WHERE uid=x ORDER BY timestamp DESC;

Сам по себе дает правильное упорядочение, как и ожидалось, но как только я сделаю запрос, упорядочение будет отменено.

Я не должен понимать, как работают вложенные операторы, кто-то может помочь, а также объяснять, почему ключевое слово DISTINCT не требуется для получения отдельных идентификаторов проекта из таблицы голосов!?

Пример по запросу;

Таблица голосов содержит отдельные голоса, поэтому, если пользователь голосует за проект три раза, он может выглядеть следующим образом;

uid     project    timestamp
34      9          10984
34      9          11093
34      9          11309

Если этот пользователь (34 в примере) затем проголосовал за другой проект, таблица голосов теперь будет выглядеть так:

uid     project    timestamp
34      9          10984
34      9          11093
34      9          11309
34      21         12612

Значения 9 и 21 затем используются для запроса таблицы проектов. Так, например, таблица проектов может содержать:

id     name           description
9      Project A      This is project A.
21     Project B      This is project B.

Мне нужен список проектов, за которые пользователь недавно проголосовал. Так что в этом случае я хочу взять проекты 21 и 9 из таблицы проектов в таком порядке, 21, затем 9 и далее в проекты, за которые пользователь голосовал дальше в прошлом.

Ответы [ 4 ]

2 голосов
/ 05 октября 2011

Я бы использовал соединение вместо подзапроса.

SELECT p.*
    FROM projects p
        INNER JOIN votes v
            ON p.id = v.project
    WHERE v.uid = x
    ORDER BY v.timestamp DESC;
1 голос
/ 05 октября 2011

Вы можете переписать это как объединение:

SELECT DISTINCT projects.* FROM projects 
   JOIN votes ON projects.id = votes.project             
   ORDER BY timestamp DESC
1 голос
/ 05 октября 2011

DISTINCT не является необходимым, поскольку, хотя подзапрос IN() может возвращать дубликаты, внешний запрос просто ищет совпадающие значения среди этих, а не отношения 1: 1.Это отличается от поведения JOIN, где вы, скорее всего, в конечном итоге получите повторяющиеся строки.

Это похоже на то, что у вас есть массив [1,2,2,4,5,5] и запрос, какое из значений из другого массива [1,2,5,6] имеет место везде в первом массиве.Ответ всегда [1,2,5].Надеюсь, эта иллюстрация не будет более запутанной.Я отредактирую это, поскольку я думаю о способах улучшить это.

Предыдущие ответы дают правильный ORDER BY.

1 голос
/ 05 октября 2011

попробуйте с ORDER BY FIELD - что-то вроде:

SELECT * FROM projects WHERE id IN(SELECT project FROM votes WHERE uid=x ORDER BY timestamp DESC) ORDER BY FIELD(id, (SELECT project FROM votes WHERE uid=x ORDER BY timestamp DESC) );
...