Можете ли вы (MySQL) упорядочить по необязательным значениям и в разных таблицах? - PullRequest
0 голосов
/ 21 декабря 2018

Итак, у меня довольно простой веб-сайт на основе PHP, который использует MySQL для некоторых своих данных.

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

Вот как выглядит база данных(sorta):

ОСНОВНОЙ СТОЛ , называемый «Главный»

    | id |  timestamp |  starttime |
    |  1 | 2010-06-10 | 2010-08-15 |
    |  2 | 2011-01-15 | 2011-03-12 |
    |  3 | 2011-01-27 | 0000-00-00 |

ПРИКЛЮЧЕННЫЙ СТОЛ , называемый «Приложения»

    | aid |  timestamp | id |
    |   1 | 2012-09-04 |  3 |
    |   2 | 2017-04-01 |  3 |

ТАБЛИЦА ПЕРЕСМОТРОВ , называемая «Ревизии»

    | rid |  timestamp | id |
    |   1 | 2014-10-10 |  1 |
    |   2 | 2018-12-25 |  2 |

Основная таблица - это то, что в основном необходимо, вложения и ревизии не важны для упорядоченного списка, который я хочу предоставить.

Теперь я хочу иметь возможность отсортировать это по «дате последнего изменения», и это проблема, потому что есть 4 значения, которые можно отсортировать по:

  1. Main.starttime (thisобновляется при определенных действиях пользователя)
  2. Attachments.timestamp (пользователи могут добавлять вложения в любое время)
  3. Revisions.timestamp (пользователь может редактировать свою главную строку, дельта записывается в Revisions как новаястрока)

ИЛИ (если ни один извышеуказанные поля существуют или равны нулю)

Main.timestamp (по умолчанию DateTime строка была создана с использованием NOW ())

Я пытался использовать GREATEST () в моем предложении ORDER BY, и это работает, но только дляMain.timestamp и Main.starttime - не для двух других значений, которые мне нужно учитывать.

Это моя текущая команда SQL:

SELECT Main.*, User.lastname, User.surname, User.title
FROM Main, User
WHERE User.uid = Main.uid AND Main.state != 0
ORDER BY $orderby LIMIT :limit OFFSET :offset

Моя переменная $ orderby обрабатываетсячерез PHP, поэтому он очищен, но в основном может быть что-то вроде:

$orderby = "Main.timestamp DESC";

или с помощью GREATEST ():

$orderby = "GREATEST(Main.timestamp, Main.starttime) DESC";

Основная проблема, с которой я сталкиваюсь, заключается в том, что не каждая строка "Main"имеет соответствующую строку в «Вложениях» или «Ревизиях», но у некоторых есть несколько.

Приведенный выше пример должен быть отсортирован как

2 > 3 > 1

, если сортировка будет работать.

Я надеюсь, что вы, ребята, можете помочь!

1 Ответ

0 голосов
/ 21 декабря 2018

Немного сложно, но это работает: https://www.db -fiddle.com / f / bUV99RzrxcHkgFyUWUMGEe / 0

Запрос

SELECT
    MAIN.id,
    MAX(MAIN.updated_at) AS 'updated_at'
FROM (
  SELECT
    M.id,
    GREATEST(
          IFNULL(M.`timestamp`, '1970-01-01 00:00:00'),
          IFNULL(M.starttime, '1970-01-01 00:00:00'),
          IFNULL(A.`timestamp`, '1970-01-01 00:00:00'),
          IFNULL(R.`timestamp`, '1970-01-01 00:00:00')
    ) AS 'updated_at'
  FROM
    main M
  LEFT JOIN
    attachment A ON M.id = A.id
  LEFT JOIN
    revision R ON M.id = R.id
) AS MAIN
GROUP BY
    MAIN.id
ORDER BY
    updated_at DESC

Объяснение

Я использовал первый запрос, чтобы выбрать все ваши основные и связанные с ними вложения и ревизии.Затем для каждого я вычислил поле updated_at, которое принимает наибольшее из множества полей (примечание: наибольший плохо работает с нулевыми значениями, следовательно, IFNULL(date, '1970-01-01 00:00:00), поэтому предполагается, что по крайней мере одна дата между основной отметкой времени,основное время начала, временная метка вложения и временная метка редакции не равны нулю).

В это время строки не группируются по основному идентификатору, поэтому в скрипте БД вы видите 4 строки.

Я использовал второй запрос, который обернул этот последний, и я использовал MAX(updated_at) AS 'updated_at', чтобы получить максимум из сгруппированных запросов (вы видите, что запрос обертки с именем AS MAIN выполняет GROUP BY MAIN.id, то естьпочему мы используем MAX, а не GREATEST, последнее занимает список полей, а не сгруппированное поле).

В конце мы упорядочиваем по нашему запросу и тада!

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...