MySQL объединяет две таблицы с максимальным значением в другом поле

У меня есть две настольные учетные записи и баланс

/---------------------\
| cid | name | mobile |
|---------------------|
|  1  | ABC  | 12345  |
|---------------------|
|  2  | XYZ  | 98475  |
\---------------------/

/----------------------------\
| date       | cid | balance |
|----------------------------|
| 2013-09-19 |  1  |   5000  |
|----------------------------|
| 2013-09-19 |  2  |   7000  |
|----------------------------|
| 2013-09-20 |  1  |    300  |
|----------------------------|
| 2013-09-20 |  2  |   4500  |
|----------------------------|
| 2013-09-21 |  2  |    600  |
\----------------------------/

Я хотел бы присоединиться к этим двум таблицам и получить баланс максимальной даты для конкретного cid.

Результат вывода как -

/--------------------------------------------\
| cid | name | mobile | date       | balance |
|--------------------------------------------|
|  1  | ABC  | 12345  | 2013-09-20 |   300   |
|--------------------------------------------|
|  2  | XYZ  | 98475  | 2013-09-21 |   600   |
\--------------------------------------------/

person newcomer    schedule 21.09.2013    source источник


Ответы (3)


Вам нужно использовать два подзапроса, например:

SELECT a.cid, a.name, a.mobile, b.date, b.balance
FROM account a 
JOIN
(
    SELECT b1.* FROM balance b1
    JOIN
    (
      SELECT cid, MAX(Date) As maxDate
      FROM balance
      GROUP BY cid
    ) b2
    ON b1.cid = b2.cid
    AND b1.date = b2.maxDate
) b
ON a.cid = b.cid;

Вывод:

CID NAME MOBILE DATE BALANCE
1 ABC 12345 September, 20 2013 00:00:00+0000 300
2 XYZ 98475 September, 21 2013 00:00:00+0000 600

См. этот SQLFiddle.

Редактировать

Как обсуждалось в комментариях, этот запрос также можно написать только с одним подзапросом:

SELECT a.cid, a.name, a.mobile, b1.date, b1.balance 
FROM account a 
JOIN balance b1 ON a.cid = b1.cid     
JOIN (
    SELECT cid, MAX(Date) As maxDate 
    FROM balance 
    GROUP BY cid
) b2 
ON b1.cid = b2.cid 
AND b1.date = b2.maxDate

См. скорректированный SQLFiddle.

person Himanshu Jansari    schedule 21.09.2013
comment
Спасибо @ hims056 Я получил желаемый результат, но его нельзя сохранить как вид. когда я пытаюсь сохранить как представление, я получаю сообщение об ошибке, поскольку SELECT -1349-View содержит подзапрос в предложении from. Пожалуйста, помогите мне. Мне нужно сохранить этот запрос в VIEW. - person newcomer; 21.09.2013
comment
@newcomer - Представления не могут содержать подзапрос. Однако вы можете создавать представления для каждого вышеуказанного подзапроса, а затем использовать эти представления в окончательном представлении. см. несколько советов здесь. - person Himanshu Jansari; 21.09.2013
comment
Спасибо, правда! - person piotr_cz; 29.09.2017
comment
Большое спасибо за это. застрял в аналогичном сценарии более часа - person Xishan; 21.10.2019
comment
@HimanshuJansari: Извините, я знаю, что вы ответили на этот вопрос довольно давно, но я столкнулся с похожей проблемой, и ваш ответ помог мне составить мой запрос. По ошибке копирования-вставки я придумал это решение: SELECT a.cid, a.name, a.mobile, b1.date, b1.balance FROM account a JOIN balance b1 ON a.cid = b1.cid JOIN (SELECT cid, MAX(Date) As maxDate FROM balance GROUP BY cid) b2 ON b1.cid = b2.cid AND b1.date = b2.maxDate. Я тестирую его туда и обратно, получаю тот же результат и просто хотел бы знать, почему ваш ответ лучше? Спасибо - person fun2life; 14.05.2021
comment
@fun2life: На самом деле твой вопрос лучше моего. Я не уверен, почему в то время я использовал два вложенных подзапроса вместо одного. Но иметь меньше подзапросов определенно лучше. Так что ваше решение намного лучше моего. Вы можете опубликовать свой ответ, указав то же самое, или можете отредактировать мой ответ, поскольку OP не активен, поэтому ваше решение можно найти в принятом ответе. - person Himanshu Jansari; 17.05.2021

SELECT a.cid, a.name, a.mobile, MAX(b.date), b.balance 
FROM account AS a
INNER JOIN balance AS b
WHERE a.cid=b.cid 
GROUP BY cid;

Извините, я не заметил столбец баланса в 3-й таблице.

SELECT a.cid, a.name, a.mobile, b.date, b.balance 
FROM account AS a
INNER JOIN (
      SELECT c.date, c.cid, c.balance FROM balance AS c
      INNER JOIN (
            SELECT cid AS cid2, MAX(date) AS date2
            FROM balance
            GROUP BY cid2) AS d
ON c.cid=d.cid2 
AND c.date=d.date2
) AS b
ON a.cid=b.cid 
GROUP BY cid;--
person Leonel Sarmiento    schedule 21.09.2013
comment
Здравствуйте, Лео. Использование агрегатной функции без группировки каждого поля даст случайные значения для этих полей. - person Himanshu Jansari; 21.09.2013

Это следующее утверждение должно дать вам требуемый результат:

SELECT cid, name, mobile, MAX(date), blance  
FROM account
LEFT JOIN balance
ON account.cid = balance.cid
GROUP BY balance.cid
person user3108497    schedule 16.12.2013