Несколько объединений с заказом по группам, не возвращая то, что я ожидаю - PullRequest
2 голосов
/ 08 июля 2011

У меня есть запрос, который я пытаюсь реализовать, но что-то не совсем верно.

Вот основы таблиц (я пропустил ненужные вещи, а также индексы и внешний ключ):

CREATE TABLE IF NOT EXISTS `PROJECT` (
      `ID` INT NOT NULL AUTO_INCREMENT ,
      `USER_ID` INT NULL ,
      `NAME` VARCHAR(40) NOT NULL ,
      `PROJECT_NUMBER` VARCHAR(30) NULL ,
      `CREATION_DATE` DATETIME NULL 


CREATE  TABLE IF NOT EXISTS `MODEL` (
      `ID` INT NOT NULL AUTO_INCREMENT ,
      `PROJECT_ID` INT NOT NULL ,

CREATE  TABLE IF NOT EXISTS `SIMULATION_SET` (
      `ID` INT NOT NULL AUTO_INCREMENT ,
      `MODEL_ID` INT NULL ,
      `CREATION_DATE` DATETIME NULL ,
      `START_TIME` DATETIME NULL ,
      `END_TIME` DATETIME NULL

Я пытаюсь сделать следующее: я хочу получить проекты, которые имеют самые последние наборы симуляций для конкретного пользователя.Это пример запроса:

SELECT P.ID, P.USER_ID, P.NAME, P.PROJECT_NUMBER, S.ID SET_ID, S.START_TIME
 FROM PROJECT P 
   INNER JOIN MODEL M ON M.PROJECT_ID=P.ID 
   INNER JOIN SIMULATION_SET S ON S.MODEL_ID=M.ID 
   WHERE P.USER_ID=5 AND S.START_TIME IS NOT NULL 
   GROUP BY P.ID 
   ORDER BY S.START_TIME DESC LIMIT 5

Я перепробовал несколько вариантов, и проблема в том, что группа, по-видимому, фильтрует его так, что я получаю первый имитационный набор в таблице для каждого проектатогда как то, что я хочу отсортировать, является последним.Без GROUP BY я получаю список всех наборов симуляции для пользователя, упорядоченных правильно.То, что я хочу, это проекты в таком порядке, но я не понимаю.

На выборочном наборе без группировки по я получаю это, которое упорядочено правильно:

+----+---------+-----------------+----------------+--------+---------------------+
| id | user_id | name            | project_number | SET_ID | start_time          |
+----+---------+-----------------+----------------+--------+---------------------+
| 14 |       5 | Krusty Krab     | 123            |    267 | 2011-07-07 14:57:15 |
| 16 |       5 | Pineapple       | p456           |    266 | 2011-07-07 12:48:58 |
| 21 |       5 | Patrick's House | US             |    265 | 2011-07-07 12:48:18 |
| 14 |       5 | Krusty Krab     | 123            |    264 | 2011-07-07 12:47:42 |
| 13 |       5 | Bikini Bottom   | B123           |    263 | 2011-07-07 12:44:07 |
| 16 |       5 | Pineapple       | p456           |    262 | 2011-07-07 12:42:52 |
| 14 |       5 | Krusty Krab     | 123            |    261 | 2011-07-07 12:41:52 |
| 16 |       5 | Pineapple       | p456           |    260 | 2011-07-07 12:40:21 |
+----+---------+-----------------+----------------+--------+---------------------+

С предложением GROUP BY я получаю это:

+----+---------+-----------------+----------------+--------+---------------------+
| id | user_id | name            | project_number | SET_ID | start_time          |
+----+---------+-----------------+----------------+--------+---------------------+
| 21 |       5 | Patrick's House | US             |    265 | 2011-07-07 12:48:18 |
| 13 |       5 | Bikini Bottom   | B123           |    263 | 2011-07-07 12:44:07 |
| 14 |       5 | Krusty Krab     | 123            |    261 | 2011-07-07 12:41:52 |
| 16 |       5 | Pineapple       | p456           |    260 | 2011-07-07 12:40:21 |
+----+---------+-----------------+----------------+--------+---------------------+

Порядок неправильный, и он тянет start_time с самого раннего, а я хочу, чтобы он был заказан с самого последнего.Первым проектом в списке должен быть Krusty Krab.Я думал, что мне может понадобиться сделать подзапросы, чтобы сделать это, но я не уверен, как.Я знаю, что мастера SQL найдут это очевидным, или, по крайней мере, я на это надеюсь!Заранее спасибо за любую помощь в этом.

Ответы [ 2 ]

0 голосов
/ 08 июля 2011

Я не знаю, какую БД вы используете, но в вашем запросе мне кажется странным группировать по идентификатору и не объединять другие результаты ...

Даже если идентификаторпервичный ключ, который, по-видимому, недопустим в Oracle, который у нас есть на работе ...

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

Учитывая, что когда вы группируете по проекту, вы показываете только одну строку для каждого проекта, как БД должна знать, что поместить в эту строку, поскольку она имеет несколько значений моделирования?Вот почему вы должны агрегировать результаты, которые не являются частью группы, ... Но в вашем случае это не сработает очень хорошо, потому что несколько агрегатов не связаны друг с другом.Использование MAX для времени начала покажет вам максимальное время начала для каждого проекта, но вы не сможете получить правильное имя, связанное с этим максимальным временем начала данного проекта.

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

0 голосов
/ 08 июля 2011

Извините, я был слишком быстр, чтобы ответить в первый раз, это не было ясно, и это также было немного неправильно ... Вот SQL, который должен делать то, что вы ищете:

SELECT P.ID, P.USER_ID, P.NAME, P.PROJECT_NUMBER, S.ID SET_ID, S.START_TIME
FROM PROJECT P
     INNER JOIN
     (SELECT P.ID, MAX(S.START_TIME) as MAX_TIME
      FROM PROJECT P 
           INNER JOIN MODEL M ON M.PROJECT_ID=P.ID 
           INNER JOIN SIMULATION_SET S ON S.MODEL_ID=M.ID 
           WHERE P.USER_ID=5 AND S.START_TIME IS NOT NULL 
      GROUP BY P.ID) PMAX ON P.ID = PMAX.ID

     INNER JOIN MODEL M ON M.PROJECT_ID=P.ID 
     INNER JOIN SIMULATION_SET S ON S.MODEL_ID=M.ID 
                                 AND S.START_TIME = PMAX.MAX_TIME

ORDER BY S.START_TIME DESC LIMIT 5

Пара замечаний:
Единственная цель внутреннего SELECT - получить максимальное время запуска для каждого проекта. Внешний выбор чем выполняет необходимые объединения снова, чтобы найти установленный идентификатор.
(Если вам не нужно SET_ID в выборе, вы можете удалить внешние объединения для MODEL и SIMULATION_SET)

Нет способа (о котором я могу думать) получить SET_ID из внутреннего соединения, поскольку вы агрегируете по идентификатору проекта, который может содержать несколько наборов.

Еще одна вещь, которую стоит отметить, - вам не нужно выражение WHERE для внешнего выбора, потому что проекты уже будут отфильтрованы, чтобы содержать только проекты с USER_ID = 5.

Надеюсь, это имеет больше смысла ...

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