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