Получить строки с наибольшими идентификаторами из объединения двух таблиц без подзапросов - PullRequest
0 голосов
/ 03 августа 2020

У меня проблемы с реализацией запроса JOIN для этих двух таблиц.

Таблица товаров содержит товары. Таблица ProductInstance содержит версию продукта с ценами, которые менялись с течением времени.

Должна быть ровно одна строка для каждого storeId, даже если он пустой, но должен содержать самый высокий productInstanceId.

введите описание изображения здесь

My Query может получать строки с наибольшими идентификаторами для каждого продукта, но игнорирует StoreIds.

Select P.id as productId, PI.id as productInstanceId, P.name, PI.storeId, PI.price from products as P

LEFT JOIN productInstances AS PI
ON PI.productId = P.id

LEFT JOIN productInstances AS PI2
ON (PI2.productId = P.id and (PI.id < PI2.id )  )
WHERE PI2.id IS NULL
AND PI.id IS NOT NULL

Создание таблиц:

CREATE SCHEMA IF NOT EXISTS `TestDB` DEFAULT CHARACTER SET utf8 ;
USE `TestDB` ;

-- -----------------------------------------------------
-- Table `TestDB`.`products`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `TestDB`.`products` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NOT NULL,
  `description` VARCHAR(45) NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `TestDB`.`productInstances`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `TestDB`.`productInstances` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `storeId` INT NULL,
  `productId` INT NOT NULL,
  `price` INT NOT NULL,
  PRIMARY KEY (`id`, `productId`),
  INDEX `fk_productInstances_products_idx` (`productId` ASC),
  CONSTRAINT `fk_productInstances_products`
    FOREIGN KEY (`productId`)
    REFERENCES `TestDB`.`products` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

ВСТАВЬТЕ ДАННЫЕ ТЕСТА, ИСПОЛЬЗУЯ ЭТОТ ЗАПРОС

INSERT INTO `TestDB`.`products` (`name`) VALUES ('Product 1');
INSERT INTO `TestDB`.`products` (`name`) VALUES ('Product 2');

INSERT INTO `TestDB`.`productInstances` (`storeId`, `productId`, `price`) VALUES ('1', '1', '111');
INSERT INTO `TestDB`.`productInstances` (`productId`, `price`) VALUES ('1', '122');
INSERT INTO `TestDB`.`productInstances` (`productId`, `price`) VALUES ('1', '133');
INSERT INTO `TestDB`.`productInstances` (`storeId`, `productId`, `price`) VALUES ('1', '1', '115');
INSERT INTO `TestDB`.`productInstances` (`storeId`, `productId`, `price`) VALUES ('2', '1', '155');

1 Ответ

1 голос
/ 03 августа 2020

Для MySql 8.0+ вы можете использовать оконную функцию ROW_NUMBER(), чтобы получить максимальный идентификатор для каждого productid и storeid:

select p.id productId, 
       pi.id productInstanceId, 
       p.name, 
       pi.storeId, 
       pi.price 
from products p 
left join (
  select *, row_number() over (partition by storeId, productId order by id desc) rn
  from productInstances
) pi on pi.productId = p.id and pi.rn = 1

Для предыдущих версий вы можете сделать то же самое с коррелированный подзапрос:

select p.id as productId, 
       pi.id as productInstanceId, 
       p.name, 
       pi.storeId, 
       pi.price 
from products p 
left join (
  select pi.* from productInstances pi
  where pi.id = (
    select max(id) 
    from productInstances 
    where productId = pi.productId and storeId <=> pi.storeId 
  )
) pi on pi.productId = p.id

См. demo . Результатов:

> productId | productInstanceId | name      | storeId | price
> --------: | ----------------: | :-------- | ------: | ----:
>         1 |                 3 | Product 1 |    null |   133
>         1 |                 4 | Product 1 |       1 |   115
>         1 |                 5 | Product 1 |       2 |   155
>         2 |              null | Product 2 |    null |  null
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...