【问题标题】:Getting data between a range and when one of the range is null在一个范围和其中一个范围为空时获取数据
【发布时间】:2014-02-21 07:04:53
【问题描述】:

需要根据a列从数据库中获取数据,并提供范围。
我有一张学生表,里面有 ID。
当我在给定的 id 范围内(即 10-20 之间)查询表时,它会返回正确的结果。
ID 是 Varchar

SELECT * 
  FROM student 
 WHERE id BETWEEN 'AB10' AND 'AB20'

但让我们假设其中一个范围未作为范围提供
1.ID从空
2. ID转AB20
那么理想情况下它应该从开始返回到提供的 id 但我没有得到任何行。 我的查询是

SELECT * 
  FROM student 
 WHERE id BETWEEN 'null' AND 'AB20' 

【问题讨论】:

  • 您的查询没有意义。你假设某种你没有告诉我们的表的顺序? “null”和“AB20”之间是什么意思,除非它是有序的?
  • 可以输入 from id 和 to_id。如果遗漏了任何一个,我需要运行查询。不确定 ID 是否会被排序
  • from_idto_id 在查询中表示在哪里?
  • 你所要做的就是使用 NVL(): WHERE id BETWEEN NVL(to_char(:id_column,'AB20') AND 'AB20'。我假设你的 id 是数字。否则不需要转换为 to_char()。

标签: mysql sql database oracle


【解决方案1】:

一种方法是停止使用 BETWEEN;无论如何,这只是两个布尔值的收缩,将它们分开。

select *
  from student
 where ( id >= :start_id
         or :start_id is null
          )
   and ( id <= :end_id
         or :end_id is null
          )
  • 如果start_id 为空,那么您将得到小于end_id 的所有内容,即从序列的“开始”到end_id 的所有内容。
  • 如果end_id 为空,那么您将获得大于start_id 的所有内容。
  • 如果两者都为 null,那么您将得到一切。

根据您的问题,我们都在这里假设列 ID 具有某种内在含义;如果没有,那么这将不起作用。

【讨论】:

    【解决方案2】:

    必须为 between 子句提供一些值,null 没有任何值。

    你可以改变你的代码来应对这种情况,这样的事情会有所帮助

    select * 
      from student 
     where id between nvl(:from_value, (select min(id) from student)) 
              and nvl(:to_value, (select max(id) from student));
    

    按照 Ben 的建议,最好使用 COALEASE

    select * 
      from student 
     where id between COALESCE(:from_value, (select min(id) from student)) 
              and COALESCE(:to_value, (select max(id) from student));
    

    COALESCE 从列表中返回第一个非空值。

    【讨论】:

    • 您可以使用DECODE() 代替NVL(),因为MIN() 将一直在内部计算,即使另一个值是NOT NULL。 (如果预计它是一个执行严重 SQL。)
    • @OracleUser 据我所知,子查询不相关,它们只会执行一次,结果将缓存在 Oracle 中以供进一步使用。如果我错了,请纠正我。无论如何,根据 OP 要求,整个查询只会被触发一次。
    • 其实你应该使用 COALESCE() 而不是 NVL() @OracleUser。 NVL() 不会短路,但 COALESCE() 会。同样,如果可能,最好avoid DECODE() in favour of CASE。桑,您的查询将使用scalar sub-query caching
    • @Ben 那是一篇不错的文章。我一直受过使用DECODE 的教育。我将进一步阅读。 San,我一直试图告诉NVL() 处理它的两个操作数。所以,我们必须使用短路的东西(COALESCE/DECODE),除非我们只处理NVL()中的值
    猜你喜欢
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-26
    • 2022-01-03
    相关资源
    最近更新 更多