AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 226679
Accepted
Billy Watsy
Billy Watsy
Asked: 2019-01-10 03:30:10 +0800 CST2019-01-10 03:30:10 +0800 CST 2019-01-10 03:30:10 +0800 CST

在 MSSQL 日期范围内或最接近日期范围内选择

  • 772

假设我们有一张桌子

CREATE TABLE [dbo].[Product](
    [ProductId] [int] NOT NULL,
    [Name] [varchar](50) NOT NULL
) 

CREATE TABLE [ProductPrice]( 
    [ProductPriceId] [int] NOT NULL,
    [ProductId] [int] NOT NULL,
    [Price] [decimal](19, 4) NOT NULL,
    [StartDate] [datetime2](7) NOT NULL,
    [EndDate] [datetime2](7) NULL
)

和样本数据

INSERT INTO ProductPrice
    ([ProductPriceId] ,[ProductId], [Price], [StartDate], [EndDate])
VALUES 
    ( 1 ,1 , 23 , '2018-12-13' , '2018-12-27'), 
    ( 2 ,1 , 26 , '2018-12-18' , '2018-12-20'), 
    ( 3 ,1 , 21 , '2018-12-10' , null), 
    ( 4 ,1 , 22 , '2018-12-28' , '2018-12-30'), 
    ( 5 ,1 , 27 , '2019-1-01' , '2019-01-18')  
;


INSERT INTO [Product]
           ([ProductId]
           ,[Name])
     VALUES
           (1 ,'Burger') ,
           (2 ,'Coke 2L') 
           ;

productID 是另一个表 Product 的外键

这张表有我们产品的价格。

问题是假设今天的日期是 2018-12-19(2018 年 12 月 19 日)

与默认日期相比,我们如何获得日期(2018-12-19)的当前价格 EndDate 不为空,价格 EndDate 将为空

问题 1 如何根据 EndDate 获得具有所需输出的价格趋势,如下所示

因此在我们的例子中,基于结束日期的最接近的日期是正确的顺序:

   -1- EndDate 2018-12-20 ( 20 Decemeber 2018 )  ProductPriceID : 2   Price : 26
   -2- EndDate 2018-12-27 ( 27 Decemeber 2018 )  ProductPriceID : 1   Price : 23
   -3- EndDate 2018-12-30 ( 30 Decemeber 2018 )  ProductPriceID : 4   Price : 22
   -4- EndDate 2019-1-01 ( 1 January 2019 )      ProductPriceID : 5   Price : 27    
   -5- EndDate NULL                              ProductPriceID : 3   Price : 21

如果范围内没有价格,则默认值为空字段的日期:因此 [EndDate NULL ProductPriceID : 3 Price : 21]

问题 2 是如何根据 EndDate 上面提到的优先级获得当前价格

当前想要的价格是:26

但是如果我这样做

 /****** Script for SelectTopNRows command from SSMS  ******/
SELECT TOP (1000) [ProductPriceId]
      ,[ProductId]
      ,[Price]
      ,[StartDate]
      ,[EndDate]
  FROM [ExcelDumps].[dbo].[ProductPrice] As p
  Where  
   (
    p.[EndDate] >= '2018-12-18' 
    OR
    p.[EndDate] is null 
   )
   order by p.[EndDate] asc

我得到:

-----------------------------------------------------------------------
ProductPriceId  ProductId   Price   StartDate   EndDate
--------------------------------------------------------------------------
3               1           21.0000 2018-12-10  NULL
2               1           26.0000 2018-12-18  2018-12-19 
1               1           23.0000 2018-12-13  2018-12-27
4               1           22.0000 2018-12-28  2018-12-30
5               1           27.0000 2019-01-01  2019-01-18

但是 null 应该在最后

问题3:以当前价格检索整个产品列表:

我试过了什么

/****** Script for SelectTopNRows command from SSMS  ******/

;with ctaCurrentPrice As
(
  -- tried gettign current price for product 
    SELECT *
  FROM [ExcelDumps].[dbo].[ProductPrice] As p
  Where  
   ( 
    p.[EndDate] >= '2018-12-18' 
    OR
    p.[EndDate] is null 
   ) 
)
Select * , 
    (
      Select Top 1 Price From  ctaCurrentPrice where ProductId = pro.[ProductId]
    ) As Price ,
    (
     Select Top 1 StartDate From  ctaCurrentPrice where ProductId = pro.[ProductId]
    ) As StartDate,
    (
     Select Top 1 EndDate From  ctaCurrentPrice where ProductId = pro.[ProductId]
    ) As EndDate
 From Product As pro

得到什么

ProductId 名称 价格 开始日期 结束日期

1       Burger  23.0000 2018-12-13  2018-12-27
2       Coke 2L NULL    NULL        NULL

其中想要的是


ProductId 名称 价格 开始日期 结束日期

1       Burger  26.0000 2018-12-18  2018-12-19 
2       Coke 2L NULL    NULL        NULL

编辑 2:

我找到了解决方案希望

SELECT Top 1 *
  FROM [ExcelDumps].[dbo].[ProductPrice] As p
  Where  
    p.[ProductId] = 1
    AND
   ( 
    p.[EndDate] >= '2018-12-18' 
    OR
    p.[EndDate] is null 
   ) 
   order by case when p.[EndDate] is null then 2 else 1 end, p.[EndDate]  asc 
sql-server select
  • 1 1 个回答
  • 1672 Views

1 个回答

  • Voted
  1. Best Answer
    McNets
    2019-01-10T06:19:35+08:002019-01-10T06:19:35+08:00

    问题 1 如何根据 EndDate 获得具有所需输出的价格趋势,如下所示

    只需使用 COALESCE 将 NULL 日期值转换为 31/12/9999,这是日期时间列允许的最大值。

    SELECT
        ProductPriceId,
        ProductId,
        Price,
        StartDate,
        EndDate
    FROM
        ProductPrice
    ORDER BY
        ProductId,
        COALESCE(EndDate, '99991231');
    
    产品价格 ID | 产品编号 | 价格 | 开始日期 | 结束日期            
    -------------: | --------: | :-------- | :----------------- | :-----------------
                 2 | 1 | 26.0000 | 18/12/2018 00:00:00 | 20/12/2018 00:00:00
                 1 | 1 | 23.0000 | 13/12/2018 00:00:00 | 27/12/2018 00:00:00
                 4 | 1 | 22.0000 | 28/12/2018 00:00:00 | 2018 年 12 月 30 日 00:00:00
                 5 | 1 | 27.0000 | 01/01/2019 00:00:00 | 18/01/2019 00:00:00
                 3 | 1 | 21.0000 | 2018 年 10 月 12 日 00:00:00 | 无效的               
    

    问题 2 是如何根据 EndDate 上面提到的优先级获得当前价格

    然后使用 OUTER APPLY 连接来获取匹配条件的第一行:

    DECLARE @PriceDate datetime = '20181219';
    
    SELECT
        p.ProductId,
        p.Name,
        pl.Price,
        pl.StartDate,
        pl.EndDate
    FROM 
        Product p
    OUTER APPLY (SELECT TOP 1
                     ProductPriceId,
                     ProductId,
                     Price,
                     StartDate,
                     EndDate
                 FROM
                     ProductPrice
                 WHERE
                     ProductId = p.ProductId
                     AND EndDate > @PriceDate 
                 ORDER BY
                     ProductId,
                     COALESCE(EndDate, '99991231')) pl;
    
    产品编号 | 姓名 | 价格 | 开始日期 | 结束日期            
    --------: | :-------- | :-------- | :----------------- | :-----------------
            1 | 汉堡 | 26.0000 | 18/12/2018 00:00:00 | 20/12/2018 00:00:00
            2 | 可乐2L | 空    | 空                | 无效的               
    

    db<>在这里摆弄

    • 2

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve