查找特定周的日期

时间:2016-10-31 09:54:35

标签: sql oracle

我想选择日期在一年中特定周的项目。

例如:

public class DoubleFontSizeConverter : IValueConverter
{
   public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   {
       // increase font size 5 times 
       return (double)value*5;
   }

   public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   {
       throw new NotImplementedException();
    }
}

第44周是从星期一31/10到星期日06/11。

我知道用

获取周数
SELECT item
FROM table
WHERE my_date in week 44

我该怎么做? 感谢。

3 个答案:

答案 0 :(得分:4)

尝试:

SELECT item
FROM table
WHERE to_char( my_date, 'IW ) = '44'

有关详细信息,请参阅此链接:
https://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements004.htm#i34924

  

IW --->一年中的一周(1-52或1-53)基于ISO标准。

答案 1 :(得分:1)

使用ISO Weeks并非易事,因为第1周可以从前一年开始,1月的第一天可以算作第52周或第53周。

因此,只提供一年没有一年的数字可能不明确(第52,53,1周)。

我为了获得ISO周的第一天而找到的最佳功能是

NEXT_DAY(TO_DATE( yearNo || '0104', 'YYYYMMDD' ) - INTERVAL '7' DAY, 'MONDAY') + ( weekNo - 1 ) * 7

因此,根据您的需要,它将是

SELECT item
FROM table
WHERE my_date 
   between NEXT_DAY(TO_DATE( yearNo || '0104', 'YYYYMMDD' ) - INTERVAL '7' DAY, 'MONDAY') + ( weekNo - 1 ) * 7
      AND 6 + (NEXT_DAY(TO_DATE( yearNo || '0104', 'YYYYMMDD' ) - INTERVAL '7' DAY, 'MONDAY') + ( weekNo - 1 ) * 7) 

实际上,“完全错误证明”的方式就是这个:

FUNCTION ISOWeekDate(weekNo INTEGER, yearNo INTEGER) RETURN DATE DETERMINISTIC IS
    res DATE;
BEGIN
    IF weekNo > 53 OR weekNo < 1 THEN
        RAISE VALUE_ERROR;      
    END IF;
    res := NEXT_DAY(TO_DATE( yearNo || '0104', 'YYYYMMDD' ) - INTERVAL '7' DAY, 'MONDAY') + ( weekNo - 1 ) * 7;
    IF TO_CHAR(res, 'fmIYYY') = yearNo THEN
        RETURN res;
    ELSE
        RAISE VALUE_ERROR;
    END IF;
END ISOWeekDate;

答案 2 :(得分:0)

如果my_date列的数据类型实际上是VARCHAR2(它不应该是,但它通常是),那么您需要先将其转换为日期,然后再返回char(字符串)格式不同。然后,如果44不一定是数字,但它可能是计算的结果,或子查询,或另一个表中的值(如果它是NUMBER数据类型),那么你需要做你正在做的事情。这有什么问题?

select item
from   your_table
where  to_number(to_char(to_date(my_date,'MM/DD/YYYY'),'IW')) = 44;

也许您想知道这是否可以更有效地完成?因此,例如,您可以将where条件写为

my_date between (something) and (something else)

允许在my_date上使用索引?答案是否定的,如果my_date是VARCHAR2格式 - 你仍然需要将它包装在to_date()内,这样你就会丢失索引。

但是,您可以在to_date(my_date)上构建一个索引函数,这也许可以帮助您进行其他查询。那么,使您的当前查询更有效的问题是有意义的。现在你遇到ISO周的复杂性没有很好地定义(你也不是说哪个YEAR),所以假设你希望日期在ISO第44周,无论它在哪一年。如果日期是纯日期(时间组件等于00:00:00),你可以这样做:

where to_date(my_date, 'MM/DD/YYYY') between 
          trunc(sysdate, 'iw') + 7 * (44 - to_number(to_char(sysdate, 'iw')))     and
          trunc(sysdate, 'iw') + 7 * (44 - to_number(to_char(sysdate, 'iw'))) + 6

右侧有很多计算,但是对于表中的所有行,它们只执行一次;他们基本上没有时间。