SQL Сервер: получить ошибку выражения с этим запросом - PullRequest
0 голосов
/ 02 апреля 2020

Таблица:

create table produts_1164 
(
    product_id int,
    new_price int,
    change_date date
);

insert into produts_1164 
values (1, 20, '2019-08-14'),
       (2, 50, '2019-08-14'),
       (1, 30, '2019-08-15'),
       (1, 35, '2019-08-16'),
       (2, 65, '2019-08-17'),
       (3, 20, '2019-08-18');

Вопрос: напишите запрос SQL, чтобы найти цены на все товары на 2019-08-16. Предположим, что цена всех продуктов до любого изменения составляет 10.

Вот мое решение:

select product_id, new_price as price 
from products
where (product_id, change_date) in (select product_id, max(change_date) 
                                    from products 
                                    where change_date <= '2019-08-16' 
                                    group by product_id)
union
select product_id, 10 as price 
from products
where product_id not in (select distinct product_id 
                         from products 
                         where change_date <= '2019-08-16');

Но я получаю эту ошибку:

[42000] [Microsoft] [ODB C Драйвер 13 для SQL Сервер] [SQL Сервер] Выражение не-логического типа, указанное в контексте, где ожидается условие, рядом с ','. (4145) (SQLExecDirectW)

Есть идеи? Спасибо

Ответы [ 2 ]

0 голосов
/ 02 апреля 2020

Если вам нужны цены для всех продуктов в данный момент времени, включая те, которые не изменились до этой даты (по умолчанию 20), вам нужно просмотреть все строки (не только те, которые до целевой даты).

Я бы использовал outer apply здесь:

select p.product_id, coalesce(p1.new_price, 20), p1.change_date
from (select distinct product_id from produts_1164) p
outer apply (
    select top 1 * 
    from produts_1164 p1 
    where p1.product_id = p.product_id and p1.change_date <= '2019-08-16'
    order by p1.change_date desc
) p1

Демонстрация на DB Fiddle :

product_id | (No column name) | change_date
---------: | ---------------: | :----------
         1 |               35 | 2019-08-16 
         2 |               50 | 2019-08-14 
         3 |               20 | <em>null</em>       
0 голосов
/ 02 апреля 2020

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

select p.*
from produts_1164 p
where p.date = (select max(p2.date)
                from produts_1164 p2
                where p2.product_id = p.product_id and
                      p2.change_date <= '2019-08-16'
               );

Или оконные функции:

select p.*
from (select p.*,
             row_number() over (partition by product_id order by change_date desc) as seqnum
      from produts_1164 p
      where p.change_date <= '2019-08-16'
     ) p
where seqnum = 1;
...