SQL выбор самой последней строки в соединении - PullRequest
1 голос
/ 21 января 2020

У меня есть 2 таблицы companies и invoices Я хочу выбрать все компании с их последней ценой счета. Я не понимаю, как это работает. Вот что я попробовал:

SELECT *
FROM companies H INNER JOIN
     invoices V
     ON H.company_id = V.BC_ID
WHERE V.ISCOMMISSIE = 0 AND
      V.DATE = (SELECT MAX(v2.DATE) FROM invoices v2 WHERE v2.BC_ID = V.BC_ID AND v2.ISCOMMISSIE = 0);

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

компаний

company_id | company_name |
   1       |   company 1  |
   2       |   company 2  | 

счета

invoice_id | BC_ID | DATE       | ISCOMMISSIE | price     |
  1        |   2   | 2020-01-01 |      0      |   340,40  |
  2        |   1   | 2020-01-11 |      0      |   240,40  |
  3        |   1   | 2020-01-08 |      0      |   250,30  |
  4        |   2   | 2020-01-18 |      0      |   150,30  |
  5        |   2   | 2020-01-19 |      1      |   150,30  |

BC_ID является такие же как company_id и ISCOMMISSIE должны быть 0. Я хочу выбрать самую последнюю дату. У кого-нибудь есть идея, как это сделать, а также сделать запрос максимально быстрым? http://sqlfiddle.com/#! 9 / 2fc3a / 1

Ответы [ 4 ]

1 голос
/ 21 января 2020

Ваш запрос в порядке:

SELECT *
FROM companies H INNER JOIN
     invoices V
     ON H.company_id = V.BC_ID
WHERE V.ISCOMMISSIE = 0 AND
      V.DATE = (SELECT MAX(v2.DATE)
                FROM invoices v2
                WHERE v2.BC_ID = V.BC_ID AND
                      v2.ISCOMMISSIE = 0
               );

Для производительности вам нужен индекс для invoices(BC_ID, ISCOMMISSIE, DATE).

Хорошей альтернативой является использование оконных функций:

SELECT *
FROM companies H INNER JOIN
     (SELECT V.*,
             ROW_NUMBER() OVER (PARTITION BY BC_ID ORDER BY DATE DESC) as seqnum
      FROM invoices V
      WHERE V.ISCOMMISSIE = 0
     ) V
     ON H.company_id = V.BC_ID
WHERE seqnum = 1;
1 голос
/ 21 января 2020

Попробуйте:

SELECT H.*, V.*
FROM companies H 
INNER JOIN invoices V ON H.company_id = V.BC_ID
INNER JOIN ( SELECT v2.BC_ID, MAX(v2.DATE) DATE
             FROM invoices v2
             WHERE v2.ISCOMMISSIE = 0
             GROUP BY v2.BC_ID ) v3 ON v.BC_ID = v3.BC_ID 
                                   AND v.DATE = v3.DATE
AND V.ISCOMMISSIE = 0

И индекс invoices (ISCOMMISSIE, BC_ID, DATE) может помочь ...

0 голосов
/ 21 января 2020

Другой способ получить ожидаемый результат:

select * from companies A join (
select * from invoices where (BC_ID,DATE) in(
select BC_ID as BC_ID, MAX(DATE) DATE from invoices where ISCOMMISSIE = 0 group by 
BC_ID
))B on A.company_id=B.BC_ID;
0 голосов
/ 21 января 2020

В зависимости от нужных вам столбцов может не потребоваться объединение с таблицей компаний. Также нет необходимости проверять iscommiss ie = 0 два раза, вы можете просто проверить его один раз в подзапросе перед присоединением.

См. Запрос ниже:

SELECT i.*
FROM invoices i
JOIN (
     SELECT i.bc_id, MAX(date) AS max_date
     FROM invoices i
     WHERE iscommissie = 0
     GROUP BY i.bc_id
) i_temp ON i.bc_id = i_temp.bc_id AND i.date = i_temp.max_date

НАЙТИ ДЕМО ЗДЕСЬ

...