Запросы MySQL UNION 2, содержащие ORDER BY

Я пытаюсь ОБЪЕДИНИТЬ два запроса, оба из которых содержат ORDER BY. Как я обнаружил, вы не можете упорядочивать запросы, которые являются частью UNION. Я просто не знаю, как еще сделать этот запрос тогда. Позвольте мне объяснить, что я пытаюсь сделать.

  1. Я пытаюсь выбрать 40 самых последних профилей и из этого списка выбрать случайный набор из 20. Затем я хочу объединить это с:
  2. Выберите 40 случайных профилей, где профиль не попадает в исходные 40 самых последних профилей, запрошенных в первом наборе.
  3. Случайным образом закажите весь этот набор из 60 записей.

Я знаю об эффективности использования функции Rand().

SELECT profileId
  FROM (SELECT profileId
          FROM profile profile2
         WHERE profile2.profilePublishDate <= Now()
      ORDER BY profile2.profilePublishDate DESC
         LIMIT 0,40) AS profile1
ORDER BY RAND()
   LIMIT 0,20
UNION (SELECT profileId
         FROM profile profile4
        WHERE profileId NOT IN (SELECT profileId
                                  FROM profile profile4
                                 WHERE profile4.profilePublishDate <= Now()
                              ORDER BY profile4.profilePublishDate DESC
                                 LIMIT 0,40)    
     ORDER BY RAND()    
        LIMIT 0,40) as profile3
ORDER BY RAND()

ОБНОВЛЕНИЕ: это решение основано на приведенной ниже справке Абхая (спасибо, Абхай):

SELECT *
FROM
(
    (
        SELECT profileId
        FROM 
        (
            SELECT profileId
            FROM profile profile2
            WHERE profile2.profilePublishDate <= Now()
            ORDER BY profile2.profilePublishDate DESC
            LIMIT 0,40
        ) AS profile1
        ORDER BY RAND()
        LIMIT 0,20
    )
    UNION
    (
        SELECT profileId
        FROM profile profile4
        WHERE profileId NOT IN (
            SELECT * FROM
            (
            SELECT profileId
            FROM profile profile4
            WHERE profile4.profilePublishDate <= Now()
            ORDER BY profile4.profilePublishDate DESC
            LIMIT 0,40
            ) AS temp2
         )
        ORDER BY RAND()    
        LIMIT 0,40
    )
) TEMP
ORDER BY RAND();

person Paolo Broccardo    schedule 18.06.2011    source источник


Ответы (2)


Это ваше решение:

SELECT *
FROM
(
    **(**
        SELECT profileId
        FROM 
        (
            SELECT profileId
            FROM profile profile2
            WHERE profile2.profilePublishDate <= Now()
            ORDER BY profile2.profilePublishDate DESC
            LIMIT 0,40
        ) AS profile1
        ORDER BY RAND()
        LIMIT 0,20
    **)**
    UNION
    (
        SELECT profileId
        FROM profile profile4
        WHERE profileId NOT IN (
            SELECT profileId
            FROM profile profile4
            WHERE profile4.profilePublishDate <= Now()
            ORDER BY profile4.profilePublishDate DESC
            LIMIT 0,40
            )
        ORDER BY RAND()    
        LIMIT 0,40
    )
) TEMP
ORDER BY RAND();

Изменения, которые я сделал:

  1. каждый из ваших запросов, являющихся частью UNION, должен быть заключен в квадратные скобки (выделен полужирным шрифтом для первого запроса; второй уже заключен в скобки)
  2. удален псевдоним profile3 для вашего второго запроса
  3. для окончательного ORDER BY RAND() вы должны создать набор результатов UNION для производной таблицы; Я дал ему TEMP как псевдоним

Я не проверял приведенный выше запрос, но надеюсь, что он должен работать. Дайте мне знать ваши выводы.

person Abhay    schedule 18.06.2011
comment
Спасибо - ваше решение решило мою проблему, однако возникла новая ошибка (эта версия MySQL еще не поддерживает подзапрос LIMIT & IN/ALL/ANY/SOME), который я также разрешил с помощью другого выбора и разместил полный запрос выше в мой оригинальный пост. Спасибо за вашу помощь в решении этого. - person Paolo Broccardo; 19.06.2011
comment
@Cheeky: Да, это способ решить эту проблему с ограничениями, которые накладывает MySQL :) - person ypercubeᵀᴹ; 19.06.2011

Вы можете заключить весь запрос в другой выбор (чтобы сделать это подзапрос) и ORDER BY RAND() в этом наборе результатов. Однако это довольно запутанно (много случайных операторов ORDER BY, когда вам нужен только один), поэтому, вероятно, будет меньше ресурсов процессора для сбора упорядоченного набора данных (т.е. только UNION из profile1 и profile3) в массив на выбранном вами языке и рандомизировать этот порядок этого массива.

person Andy    schedule 18.06.2011
comment
Ему нужен внутренний ORDER BY RAND() - person ypercubeᵀᴹ; 18.06.2011
comment
@ypercube, почему требуется внутренний ORDER BY, когда весь набор результатов переупорядочивается? - person Andy; 18.06.2011
comment
потому что он используется в сочетании с LIMIT 40 для выбора 40 случайных строк из одной части таблицы и 20 случайных строк из другой (с LIMIT 20). - person ypercubeᵀᴹ; 18.06.2011
comment
@ypercube спасибо, забыл повторно RTFQ после вашего первого комментария, ответ обновлен;) - person Andy; 18.06.2011