请问用sql实现通过已知的年,月,第几周和周几,得到具体的日期
请教用sql实现通过已知的年,月,第几周和周几,得到具体的日期
请教用sql实现通过已知的年,月,第几周和周几,得到具体的日期
已知年,月,第几周和周几,
得到具体的日期?
xichenx 发表于 2006-3-2 11:20
顶上去,希望高手能看到
sxxj 发表于 2006-3-2 13:53
一个比较麻烦的方法:
DECLARE
I INT;
STR VARCHAR(20);
INPUT VARCHAR(20);
BEGIN
INPUT := &YYYY || LPAD(&MM, 2, '0') || &W || &D;
FOR I IN 1 .. 31 LOOP
SELECT TO_CHAR(TO_DATE(&YYYY || '-' || &MM || '-' || I), 'YYYYMMWD')
INTO STR
FROM DUAL;
IF STR = INPUT THEN
DBMS_OUTPUT.PUT_LINE(&YYYY || '-' || &MM || '-' || I);
EXIT;
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Input Error!');
END;
输入项中
yyyy——年
mm——月
w——第几周
d——周几的数字表示。(星期天=1,星期一=2,...)
lawolfgang 发表于 2006-3-2 15:06
如何定义第几周?
每7天一周?oracle 这样计算。
周日是第一天?
sxxj 发表于 2006-3-2 15:15
看看Windows日历吧,周日是第一天!
summer.wang 发表于 2006-3-2 15:41
有select語句可以查出某個日期是一年裡面的第幾天,和一周裡面的第幾天的!
lawolfgang 发表于 2006-3-2 16:03
谢谢。
:lihai我还真的看了又看。
select to_char( mydate, 'WW' ) form dual
select to_char( mydate, 'IW' ) form dual
的结果是不一样的。
还有在一周里,周日的序号是 1,而不是7。
lawolfgang 发表于 2006-3-2 16:14
希望对你有帮助.
-- -------------------------
-- 一周里的第几个星期。
-- 周一是一周的第一天 。
--
function getWeekInMonth( p_date DATE )
return NUMBER
is
v_Result number;
v_No01 DATE;
v_Month NUMBER;
begin
-- 本月的第一天。
v_No01 := add_months( last_day( p_date ) + 1, -1 );
WHILE TRUE Loop
SELECT to_number( to_char( v_No01, 'IW' ) ),
to_number( to_char( v_No01, 'MM' ) )
INTO v_Result,
v_Month
FROM dual;
IF v_Month > 1 THEN EXIT;
END IF;
IF v_Result = 52 THEN v_No01 := v_No01 + 1;
ELSE EXIT;
END IF;
END LOOP;
-- 一周里的第几个星期。
SELECT to_number( to_char( p_date, 'IW' ) ) -
to_number( to_char( v_No01, 'IW' ) ) + 1
INTO v_Result
FROM dual;
--
return v_Result;
end ;
-- -------------------------
--
-- p_WeekDay 取值从1到7,依次对应周日、周一到周六。
--
-- SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
--
function getDate(
p_Year IN NUMBER, -- 年
p_Month IN NUMBER, -- 月
p_WeekNo IN NUMBER, -- 第几周
p_WeekDay IN NUMBER -- 周几,为了便于使用而使用数字。
)
return date
is
v_First DATE;
v_Text VARCHAR2( 20 );
v_ActWeek NUMBER;
BEGIN
IF p_WeekNo > 5 THEN RETURN NULL;
END IF;
v_Text := to_char( p_Year ) || '-' || to_char( p_Month ) || '-01';
v_First := to_date( v_Text, 'yyyy-mm-dd' );
WHILE TRUE Loop
SELECT NEXT_DAY( v_First, p_WeekDay )
INTO v_First
FROM dual ;
-- 问题:下列语句异常??????
--v_First := NEXT_DAY( v_First, 1 );
v_ActWeek := getWeekInMonth( v_First );
IF v_ActWeek = p_WeekNo THEN EXIT;
END IF;
IF v_ActWeek > p_WeekNo THEN v_First := NULL;
END IF;
IF v_ActWeek > p_WeekNo THEN EXIT;
END IF;
END LOOP;
RETURN v_First ;
end ;
sxxj 发表于 2006-3-2 18:08
直接用select to_char(sysdate,'W') from dual就可以查询出第几周了,为什么要用to_char(sysdate,'IW')?见笑了,IW参数没用过:)
lawolfgang 发表于 2006-3-2 18:36
不好意思,让你见笑了. 请你仔细检查一下你的 SQL 运行结果.
'W' 的结果是从1号开始,每7天一个星期。7号一定在第一周。
但是2006-3-6 就是第二周了。你如何解释?
OK?
uni2046 发表于 2006-3-2 19:40
y - 年份
m - 月
w - 周
dow - 星期, (1 = 星期日, 7=星期六)
uni2046 发表于 2006-3-2 19:45
WW : 當年的一月一日為第一周.
IW : 當年的一月一日後第一個星期一為第一周. 所以 2005-1-1 是 2004 年的第53周.
sxxj 发表于 2006-3-3 10:52
从Windows日历上看,2006-3-6不是第2周,而是第一周的周一,2006-3-7是第1周的周2,2006-3-8是第2周的周3,而2006-3-14才是第2周的周2。我对此的理解是:因为2006-3-1是第1周的周3,那么2006-3月的第1周的周日、周1、周2是多少呢?我认为是5、6、7。对了,这样解释比较清楚,2006-3-14是2006-3月的第2个星期2。
lawolfgang 发表于 2006-3-3 15:25
很遗憾,我不认为: “2006-3-6不是第2周,而是第一周的周一”。我依然认为: 2006-3-6是3月的第2周的周一。不过争论这个实在没有任何意义,一切有1楼说了算。
如果问题改变成为:
已知 ***某年某月的第n个星期w***,算出具体日期。问题可能就简单了。
<pre>
CREATE OR REPLACE FUNCTION get_date2(
y number,
m number,
idx number, -- 第几个n
dow NUMBER -- 星期 m
)
RETURN DATE
IS
v_date DATE;
v_cnt NUMBER := 0;
BEGIN
IF idx NOT BETWEEN 1 AND 5 THEN RETURN NULL;
END IF;
-- 上个月的最后一天.
v_date := TO_DATE( y || '-' || m, 'YYYY-MM' ) - 1;
WHILE TRUE LOOP
SELECT next_day( v_date , dow )
INTO v_date
FROM dual ;
v_cnt := v_cnt + 1;
IF idx = v_cnt THEN EXIT;
END IF;
END LOOP;
RETURN v_date;
END;
</pre>
请教用sql实现通过已知的年,月,第几周和周几,得到具体的日期
已知年,月,第几周和周几,
得到具体的日期?
xichenx 发表于 2006-3-2 11:20
顶上去,希望高手能看到
sxxj 发表于 2006-3-2 13:53
一个比较麻烦的方法:
DECLARE
I INT;
STR VARCHAR(20);
INPUT VARCHAR(20);
BEGIN
INPUT := &YYYY || LPAD(&MM, 2, '0') || &W || &D;
FOR I IN 1 .. 31 LOOP
SELECT TO_CHAR(TO_DATE(&YYYY || '-' || &MM || '-' || I), 'YYYYMMWD')
INTO STR
FROM DUAL;
IF STR = INPUT THEN
DBMS_OUTPUT.PUT_LINE(&YYYY || '-' || &MM || '-' || I);
EXIT;
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Input Error!');
END;
输入项中
yyyy——年
mm——月
w——第几周
d——周几的数字表示。(星期天=1,星期一=2,...)
lawolfgang 发表于 2006-3-2 15:06
如何定义第几周?
每7天一周?oracle 这样计算。
周日是第一天?
sxxj 发表于 2006-3-2 15:15
引用
Originally posted by lawolfgang at 2006-3-2 03:06 PM:
如何定义第几周?
每7天一周?oracle 这样计算。
周日是第一天?
如何定义第几周?
每7天一周?oracle 这样计算。
周日是第一天?
看看Windows日历吧,周日是第一天!
summer.wang 发表于 2006-3-2 15:41
有select語句可以查出某個日期是一年裡面的第幾天,和一周裡面的第幾天的!
lawolfgang 发表于 2006-3-2 16:03
引用
Originally posted by sxxj at 2006-3-2 15:15:
看看Windows日历吧,周日是第一天!
看看Windows日历吧,周日是第一天!
谢谢。
:lihai我还真的看了又看。
select to_char( mydate, 'WW' ) form dual
select to_char( mydate, 'IW' ) form dual
的结果是不一样的。
还有在一周里,周日的序号是 1,而不是7。
lawolfgang 发表于 2006-3-2 16:14
希望对你有帮助.
-- -------------------------
-- 一周里的第几个星期。
-- 周一是一周的第一天 。
--
function getWeekInMonth( p_date DATE )
return NUMBER
is
v_Result number;
v_No01 DATE;
v_Month NUMBER;
begin
-- 本月的第一天。
v_No01 := add_months( last_day( p_date ) + 1, -1 );
WHILE TRUE Loop
SELECT to_number( to_char( v_No01, 'IW' ) ),
to_number( to_char( v_No01, 'MM' ) )
INTO v_Result,
v_Month
FROM dual;
IF v_Month > 1 THEN EXIT;
END IF;
IF v_Result = 52 THEN v_No01 := v_No01 + 1;
ELSE EXIT;
END IF;
END LOOP;
-- 一周里的第几个星期。
SELECT to_number( to_char( p_date, 'IW' ) ) -
to_number( to_char( v_No01, 'IW' ) ) + 1
INTO v_Result
FROM dual;
--
return v_Result;
end ;
-- -------------------------
--
-- p_WeekDay 取值从1到7,依次对应周日、周一到周六。
--
-- SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
--
function getDate(
p_Year IN NUMBER, -- 年
p_Month IN NUMBER, -- 月
p_WeekNo IN NUMBER, -- 第几周
p_WeekDay IN NUMBER -- 周几,为了便于使用而使用数字。
)
return date
is
v_First DATE;
v_Text VARCHAR2( 20 );
v_ActWeek NUMBER;
BEGIN
IF p_WeekNo > 5 THEN RETURN NULL;
END IF;
v_Text := to_char( p_Year ) || '-' || to_char( p_Month ) || '-01';
v_First := to_date( v_Text, 'yyyy-mm-dd' );
WHILE TRUE Loop
SELECT NEXT_DAY( v_First, p_WeekDay )
INTO v_First
FROM dual ;
-- 问题:下列语句异常??????
--v_First := NEXT_DAY( v_First, 1 );
v_ActWeek := getWeekInMonth( v_First );
IF v_ActWeek = p_WeekNo THEN EXIT;
END IF;
IF v_ActWeek > p_WeekNo THEN v_First := NULL;
END IF;
IF v_ActWeek > p_WeekNo THEN EXIT;
END IF;
END LOOP;
RETURN v_First ;
end ;
sxxj 发表于 2006-3-2 18:08
直接用select to_char(sysdate,'W') from dual就可以查询出第几周了,为什么要用to_char(sysdate,'IW')?见笑了,IW参数没用过:)
lawolfgang 发表于 2006-3-2 18:36
引用
Originally posted by sxxj at 2006-3-2 18:08:
直接用select to_char(sysdate,'W') from dual就可以查询出第几周了,为什么要用to_char(sysdate,'IW')?见笑了,IW参数没用过:)
直接用select to_char(sysdate,'W') from dual就可以查询出第几周了,为什么要用to_char(sysdate,'IW')?见笑了,IW参数没用过:)
不好意思,让你见笑了. 请你仔细检查一下你的 SQL 运行结果.
'W' 的结果是从1号开始,每7天一个星期。7号一定在第一周。
但是2006-3-6 就是第二周了。你如何解释?
OK?
uni2046 发表于 2006-3-2 19:40
CREATE OR REPLACE FUNCTION get_date ( y number, m number, w number, dow number) RETURN DATE IS v_w NUMBER; v_date DATE; BEGIN v_w := w; v_date := TO_DATE( y||'-'||m, 'YYYY-MM' ); IF dow < TO_CHAR(v_date, 'D') THEN v_w := v_w + 1; END IF; v_date := NEXT_DAY(v_date - 7, 'SUNDAY'); v_date := v_date + 7 * (v_w-1)+ dow-1; RETURN v_date; END;
y - 年份
m - 月
w - 周
dow - 星期, (1 = 星期日, 7=星期六)
uni2046 发表于 2006-3-2 19:45
WW : 當年的一月一日為第一周.
IW : 當年的一月一日後第一個星期一為第一周. 所以 2005-1-1 是 2004 年的第53周.
sxxj 发表于 2006-3-3 10:52
引用
Originally posted by lawolfgang at 2006-3-2 06:36 PM:
不好意思,让你见笑了. 请你仔细检查一下你的 SQL 运行结果.
'W' 的结果是从1号开始,每7天一个星期。7号一定在第一周。
但是2006-3-6 就是第二周了。你如何解释?
OK?
不好意思,让你见笑了. 请你仔细检查一下你的 SQL 运行结果.
'W' 的结果是从1号开始,每7天一个星期。7号一定在第一周。
但是2006-3-6 就是第二周了。你如何解释?
OK?
从Windows日历上看,2006-3-6不是第2周,而是第一周的周一,2006-3-7是第1周的周2,2006-3-8是第2周的周3,而2006-3-14才是第2周的周2。我对此的理解是:因为2006-3-1是第1周的周3,那么2006-3月的第1周的周日、周1、周2是多少呢?我认为是5、6、7。对了,这样解释比较清楚,2006-3-14是2006-3月的第2个星期2。
lawolfgang 发表于 2006-3-3 15:25
很遗憾,我不认为: “2006-3-6不是第2周,而是第一周的周一”。我依然认为: 2006-3-6是3月的第2周的周一。不过争论这个实在没有任何意义,一切有1楼说了算。
如果问题改变成为:
已知 ***某年某月的第n个星期w***,算出具体日期。问题可能就简单了。
<pre>
CREATE OR REPLACE FUNCTION get_date2(
y number,
m number,
idx number, -- 第几个n
dow NUMBER -- 星期 m
)
RETURN DATE
IS
v_date DATE;
v_cnt NUMBER := 0;
BEGIN
IF idx NOT BETWEEN 1 AND 5 THEN RETURN NULL;
END IF;
-- 上个月的最后一天.
v_date := TO_DATE( y || '-' || m, 'YYYY-MM' ) - 1;
WHILE TRUE LOOP
SELECT next_day( v_date , dow )
INTO v_date
FROM dual ;
v_cnt := v_cnt + 1;
IF idx = v_cnt THEN EXIT;
END IF;
END LOOP;
RETURN v_date;
END;
</pre>