zoukankan      html  css  js  c++  java
  • 根据指定时间找出最接近的预约时间

    数据库环境:SQL SERVER 2008R2

    有用户表和预约时间表如下:

    用户表

    预约时间表

    要求得到如下结果

    有以下限制条件:

    1.有预约时间大于等于今天的,取最早的日期

    2.没有大于今天的预约时间,取过去预约时间最近的一条

    3.没有预约时间的,则预约时间显示为NULL

    初看题目时,觉得很简单,用分析函数整一下就OK了。但真正去实现的时候,发现并不是自己想象的那么简单。

    用分析函数整了一会,没有什么好的思路,就暂时把预约时间表分成2部分,一部分是预约时间大于等于今天的,

    另一部分则是预约时间小于今天。分别排序后用union all关联起来。

    1.建表,准备测试数据

    CREATE TABLE users (id INT,username VARCHAR(10))
    INSERT INTO users(id,username) VALUES(1,'张三')
    INSERT INTO users(id,username) VALUES(2,'李四')
    INSERT INTO users(id,username) VALUES(3,'王五')
    
    CREATE TABLE appointment(id INT,userid INT,ordertime DATE)
    INSERT INTO appointment(id,userid,ordertime)VALUES(1,1,'2015-07-30')
    INSERT INTO appointment(id,userid,ordertime)VALUES(2,1,'2015-07-23')
    INSERT INTO appointment(id,userid,ordertime)VALUES(3,2,'2015-07-26')
    INSERT INTO appointment(id,userid,ordertime)VALUES(4,1,'2015-07-31')
    INSERT INTO appointment(id,userid,ordertime)VALUES(5,2,'2015-07-21')
    View Code

    2.union all实现

    WITH    x0
              AS ( /*大于等于今天的预约时间分组取最小值*/ SELECT userid ,
                                                MIN(ordertime) ordertime
                                         FROM   dbo.appointment
                                         WHERE  ordertime >= GETDATE()
                                         GROUP BY userid
                   UNION ALL
                   /*小于今天的预约时间分组取最大值*/
                   SELECT   userid ,
                            MAX(ordertime) ordertime
                   FROM     dbo.appointment
                   WHERE    ordertime < GETDATE()
                   GROUP BY userid
                 ),/*合并之后可能会存在一个客户有2个预约时间段,将结果集分组取最大值*/
            x1
              AS ( SELECT   userid ,
                            MAX(ordertime) ordertime
                   FROM     x0
                   GROUP BY userid
                 )
        SELECT  u.username ,
                p.ordertime
        FROM    users u
                LEFT JOIN x1 p ON p.userid = u.id
    View Code

    再回来审了一下题,发觉自己钻进死胡同里头了。其实,通过case when比较预约时间和今天的大小,

    然后用group by分组求就行。

    3.case when+group by实现

    WITH    x0
              AS ( SELECT   userid ,
                            MAX(CASE WHEN ordertime < GETDATE() THEN ordertime
                                END) AS max_ordertime ,--早于今天,取预约时间最大值
                            MIN(CASE WHEN ordertime >= GETDATE() THEN ordertime
                                END) AS min_ordertime  --预约时间大于等于今天,取预约时间最小值
                   FROM     appointment
                   GROUP BY userid
                 )
        SELECT  a.username ,
                ISNULL(b.min_ordertime, b.max_ordertime) AS ordertime
        FROM    users a
                LEFT JOIN x0 b ON b.userid = a.id
    View Code

    绕来绕去,就这么简单!

  • 相关阅读:
    UUID工具类
    jax-rs 标准以及 结合 resteasy的使用
    Mina.Net实现的断线重连
    Mina.Net实现的UDP协议消息收发Demo
    MySql 比Replace Into更适合的用法,外加SqlServer的方式。
    MySql【Insert Select Not Exist】判断记录再添加值的方案
    MySql中存储过程中的@变量总是无法执行,提示Parameter '@XXX' must be defined
    Go语言使用Beego的ORM插入Mysql后,时区不一致的解决方案
    Go语言中Path包用法
    C#(WPF和WinForm)在普通类中调用到主线程的方法,SynchronizationContext的用法。
  • 原文地址:https://www.cnblogs.com/boss-he/p/4681125.html
Copyright © 2011-2022 走看看