SQL 服务器查找加入顺序中的日期

SQL Server Find the date in joining order

我正在使用 MS-SQL 服务器有两个表

会员资格

+---+-----------------+---------------------+----------------
|   | membershipName  |      createddate    |   price       |
+---+-----------------+---------------------+----------------
| 1 | Swimming        |        2010-01-01   |     30        |
| 2 | Swimming        |        2010-05-01   |     32        |
| 3 | Swimming        |        2011-01-01   |     35        |
| 4 | Swimming        |        2012-01-01   |     40        |
+---+-----------------+---------------------+----------------

会员

+---+-----------------+---------------------+-----------------
|   | memberName      |      membership     |   joiningDate  |
+---+-----------------+---------------------+-----------------
| 0 | Andy            |        Swimming     |    2008-02-02  |   
| 1 | John            |        Swimming     |    2010-02-02  |
| 2 | Andy            |        Swimming     |    2011-02-02  |
| 3 | Alice           |        Swimming     |    2015-02-02  |
+---+-----------------+---------------------+----------------

我想找到该会员在合适时间段的会员价格

例如

最好的逻辑是看

如果加入日期在两个开始日期之间

 if yes choose the earlier date

如果不是

   if the joining date is before the earlier date then use the earliest date
   if the joining date is after  the latest  date then use the latest date

我是一名 Java 程序员,在 sql 中执行此操作对我来说非常棘手,任何提示都很好!

希望我没听错。您可以这样尝试:

声明table变量到模型一个测试场景:

DECLARE @membership TABLE(id INT, membershipName VARCHAR(100),createddate DATETIME,price DECIMAL(10,4));
INSERT INTO @membership VALUES
 (1,'Swimming',{d'2010-01-01'},30)
,(2,'Swimming',{d'2010-05-01'},32)
,(3,'Swimming',{d'2011-01-01'},35)
,(4,'Swimming',{d'2012-01-01'},40);

DECLARE @member TABLE(id INT,memberName VARCHAR(100),membership VARCHAR(100),joiningDate DATETIME);
INSERT INTO @member VALUES
 (0,'Andy','Swimming',{d'2008-02-02'})   
,(1,'John','Swimming',{d'2010-02-02'})
,(2,'Andy','Swimming',{d'2011-02-02'})
,(3,'Alice','Swimming',{d'2015-02-02'});

因为你在 SQL-Server 2012,你很幸运。您可以使用 LEAD:

CTE "Intervalls" 将 return 成员资格 table 原样 并且它会在下一行前一秒添加一列createddateLEAD 帮助您获得 稍后出现的 行的值。首先我拿走一秒钟,然后我设置一个非常高的日期以防 NULL:

WITH Intervalls AS
(
    SELECT *
          ,ISNULL(DATEADD(SECOND ,-1,LEAD(createddate) OVER(ORDER BY createddate)),{d'2100-01-01'}) AS EndOfIntervall
    FROM @membership AS ms
)

--SELECT 读取所有成员并将他们加入到他们的日期在 "Intervalls" 范围内的成员中。只有 比第一个 早的情况必须特殊处理:

SELECT m.*
      ,ISNULL(i.price, CASE WHEN YEAR(m.joiningDate)<(SELECT MIN(x.createddate) FROM @membership as x) 
                            THEN (SELECT TOP 1 x.price FROM @membership AS x ORDER BY x.createddate ASC) END)
FROM @member AS m
LEFT JOIN Intervalls AS i ON m.joiningDate BETWEEN i.createddate AND i.EndOfIntervall

更新更好的方法(感谢 Paparis)

SELECT m.*
      ,ISNULL(Corresponding.price, (SELECT TOP 1 x.price FROM @membership AS x ORDER BY x.createddate ASC)) AS price
FROM @member AS m
OUTER APPLY
(
    SELECT TOP 1 ms.price 
    FROM @membership AS ms
    WHERE ms.createddate<=m.joiningDate
    ORDER BY ms.createddate DESC
) AS Corresponding

更新 2:更简单!

SELECT m.*
      ,ISNULL
      (
          (
            SELECT TOP 1 ms.price 
            FROM @membership AS ms
            WHERE ms.createddate<=m.joiningDate
            ORDER BY ms.createddate DESC
          ), 
          (
            SELECT TOP 1 x.price FROM @membership AS x ORDER BY x.createddate ASC
          )
      ) AS price
FROM @member AS m

希望我理解正确。试试这个:

SELECT TOP 1 ms.Price
FROM membership ms
LEFT JOIN member m
ON m.joiningdate > ms.createdate
WHERE m.id = 3
ORDER BY price DESC