MYSQL - Сгруппировать и выбрать самый высокий результат и использовать JOIN? - PullRequest
0 голосов
/ 09 января 2019

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

Table: Projects 
ID,Name,invoiceTotal,department
1,Project1,100,1
2,Project2,200,3
3,Project3,300,2
4,Project4,100,2
5,Project5,400,1


Table: Manning
ProjectID,timestamp
1,1547038287
1,1515558287
1,1501118287
5,1471118287
5,1481118287

Я играл с использованием PHP, чтобы сначала выполнить запрос с внутренним объединением, чтобы я мог получить данные обеих таблиц.

SELECT
project.ID,
project.name,
project.invoiceTotal,
manning.timestamp
FROM
manning
INNER JOIN projects ON project.ID = manning.ProjectID
WHERE
project.department = 1 AND
manning.timestamp BETWEEN 1547038287 AND 1301118287
ORDER BY
manning.timestamp ASC

Затем я перебираю PHP и запускаю процедурный код, чтобы отсортировать данные и затем отобразить их. Проблема в том, что это медленно, и это определенно не самый эффективный способ сделать это.

Итак, с данными этого примера я хотел бы получить результат:

1,Project1,100,1547038287
5,Project5,400,1481118287

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

Спасибо за любую помощь. Я пытался использовать sqlfiddle.com, но сейчас мне кажется, что он не работает :(

Ответы [ 3 ]

0 голосов
/ 09 января 2019

Попробуйте:

SELECT
    p.ID,
    p.name,
    p.invoiceTotal,
    maxm.ts
FROM
    project p
    INNER JOIN (
        SELECT m.projectID, max(m.timestamp) ts
        FROM manning m
        WHERE p.ID = m.ProjectID AND m.timestamp BETWEEN 1301118287 AND 1547038287
        GROUP BY m.projectID
    ) maxm ON maxm.projectID = p.id
ORDER BY m.timestamp ASC
0 голосов
/ 09 января 2019

Если вы используете MySQL 8+ или более поздней версии, то хороший способ справиться с этим - использовать ROW_NUMBER():

WITH cte AS (
    SELECT p.ID, p.Name, p.invoiceTotal, m.timestamp,
        ROW_NUMBER() OVER (PARTITION BY m.ProjectID ORDER BY m.timestamp DESC) rn
    FROM Projects p
    INNER JOIN Manning m
        ON p.ID = m.ProjectID
    WHERE m.timestamp BETWEEN 1301118287 and 1547038287
)

SELECT ID, Name, invoiceTotal, timestamp
FROM cte
WHERE rn = 1;

enter image description here

Демо

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

0 голосов
/ 09 января 2019

Не объединяйте все строки набора, а только самую последнюю для каждого проекта:

select
  p.ID,
  p.name,
  p.invoiceTotal,
  m.max_timestamp
from projects p
join
(
  select projectid, max(timestamp) as max_timestamp
  from manning
  where timestamp between 1301118287 and 1547038287
  group by projectid
) m on m.projectid = p.id
where p.department = 1;

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

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