Лучший способ объединить две таблицы SQL с несколькими условиями и одним условием макс - PullRequest
0 голосов
/ 18 мая 2018

У меня есть две таблицы: Материалы и инвентарь.

Я хочу получить список всех материалов с их последним запасом, если есть, в противном случае просто ноль.

ТАБЛИЦА - МАТЕРИАЛЫ

id        | material    | 
==========================
1         |Lily - Blue    
2         |Lily - Orange    
3         |Lily - White
4         |Rose - Blue    
5         |Rose - Orange    
6         |Rose - White

ТАБЛИЦА - ИНВЕНТАРЬ

id        | date      | material   | final_stock | entry_time           | 
=========================================================================
1         |2018-05-18 |Lily - Blue |  30         |  2018-05-18 09:06:48 |        
2         |2018-05-18 |Lily - white|  10         |  2018-05-18 10:32:27 |        
3         |2018-05-18 |Lily - Blue |  90         |  2018-05-18 15:30:31 |   

мой запрос:

select materials.material, max(inventory.final_stock) from materials left join 
inventory on materials.material = inventory.material

вывод

material    | max(inventory.final_stock)| 
========================================
Lily - Blue |90

вывод необходим >>

date       | material     | max(inventory.final_stock)| 
======================================================
2018-05-18 | Lily - Blue  |90
2018-05-18 | Lily - Orange|0
2018-05-18 | Lily - white |10
2018-05-18 | Rose - Blue  |0    
2018-05-18 | Rose - Orange|0    
2018-05-18 | Rose - white |0    

Ответы [ 4 ]

0 голосов
/ 18 мая 2018

просто добавьте подзапрос, чтобы заполнить недостающие элементы, затем используйте условные выражения для заполнения пустых полей.Приведенный ниже запрос соответствует условиям, заданным в вашем вопросе.

Помните, что в «живой» системе я бы не просто искал max (final_stock) на любую конкретную дату в качестве элемента «final_stock».Если предполагается, что 'entry_time' - самая последняя запись для данного товара, я бы повторно обработал этот запрос, чтобы использовать его в качестве самой последней 'записи инвентаря' для ссылки.Но при этом открывается вопрос о том, разрешено ли кому-либо в вашей системе обновлять записи инвентаризации.

SELECT 
  ifnull(C.date,(SELECT max(date) FROM inventory)) AS date,
  C.material,
  ifnull(max(D.final_stock),0) AS final_stock 
FROM (
  SELECT
    max(B.date) AS date,
    A.material 
  FROM materials A LEFT JOIN inventory B ON A.material = B.material 
  GROUP BY A.material
  ) AS C LEFT JOIN inventory D ON C.material=D.material AND C.date = D.date 
  GROUP BY C.material,C.date
  ORDER BY C.material,C.date

результаты ниже

date        material        final_stock
2018-05-18  Lily - Blue     90
2018-05-18  Lily - Orange   0
2018-05-18  Lily - White    10
2018-05-18  Rose - Blue     0
2018-05-18  Rose - Orange   0
2018-05-18  Rose - White    0

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

SELECT 
  ifnull(D.date,(SELECT max(date) FROM inventory)) AS date,
  C.material,
  ifnull(D.final_stock,0) AS final_stock 
FROM (
  SELECT
    max(B.entry_time) as entry_time,
    A.material 
  FROM materials A LEFT JOIN inventory B ON A.material = B.material 
  GROUP BY A.material
  ) AS C LEFT JOIN inventory D ON 
    C.material=D.material AND 
    C.entry_time = D.entry_time
    ORDER BY C.material
0 голосов
/ 18 мая 2018

Вы также можете сделать JOIN с subquery:

select m.material, coalesce(i.final_stock, 0) as final_stock
from materials m 
left outer join (select material, max(final_stock) final_stock
                 from INVENTORY 
                 group by material  
                 ) i on i.material = m.material;
0 голосов
/ 18 мая 2018

Попробуйте это;

with inv as
(
select  m.material
       ,i.date
       ,i.final_stock
       ,Max(i.Entry_time) over (Partition By i.material) maxLog
from materials m
left join inventory i on m.material = i.material 
)
Select date, material, final_stock
From inv where entry_time = maxLog
0 голосов
/ 18 мая 2018

Один метод является коррелированным подзапросом:

select m.*,
       coalesce( (select i.final_stock
                  from inventory i
                  where i.material = m.material
                  order by i.entry_time desc
                  limit 1
                 ), 0) as final_stock
from materials m;

Обратите внимание, что одна из основных причин наличия id в таблице заключается в том, что его можно использовать для отношений внешнего ключа.Следовательно, inventory должен иметь столбец material_id, а не material.

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