【问题标题】:SQL Server: get expression error with this querySQL Server:使用此查询获取表达式错误
【发布时间】:2020-07-14 14:27:27
【问题描述】:

表:

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][ODBC Driver 13 for SQL Server][SQL Server]在预期条件的上下文中指定的非布尔类型表达式,靠近“,”。 (4145) (SQLExecDirectW)

对此有任何想法吗?谢谢

【问题讨论】:

  • 我不认为你可以有多个列与 sqlserver 中的 IN 相比。

标签: sql sql-server tsql greatest-n-per-group window-functions


【解决方案1】:

如果您想要 所有 产品在给定时间点的价格,包括在该日期之前未更改的产品(默认值为 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

Demo on DB Fiddle

产品编号 | (无列名) |改变日期 ---------: | ---------------: | :---------- 1 | 35 | 2019-08-16 2 | 50 | 2019-08-14 3 | 20 |

【讨论】:

    【解决方案2】:

    一种方法是相关子查询:

    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;
    

    【讨论】:

      猜你喜欢
      • 2023-04-06
      • 2012-08-02
      • 2011-04-25
      • 1970-01-01
      • 2015-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-29
      相关资源
      最近更新 更多