我编写了一个存储过程,要在三年内每周进行迭代。但是它不起作用,并返回模糊的错误消息。
#1064-您的SQL语法有错误;检查与您的MariaDB服务器版本相对应的手册以获取正确的语法,以在第18行的''附近使用
DELIMITER $$
CREATE PROCEDURE loop_three_years()
BEGIN
declare y INT default 2016;
declare m int default 4;
declare d int default 20;
WHILE y <= 2019 DO
WHILE YEARWEEK(concat(y, '-', m, '-', d)) <= 53 DO
WHILE m < 12 DO
WHILE (m = 2 and d <= 29) OR (d <=30 and m in(4, 6,9,11)) OR ( m in(1,3,5,7,8,10,12) AND d <= 31) DO
set d = d + 7;
SELECT YEARWEEK(concat(y, '-', m, '-', d));
END WHILE;
set d=1;
END WHILE;
set m = 1;
SET y = y + 1;
END WHILE;
END
$$
当我将其用作最少的零件时,它们可以工作,所以我不确定重组的问题是什么。同样不确定是否有更好的方法可以做到这一点。 (select
仅用于测试,当我使用真实代码时,它将是insert
。
答案 0 :(得分:1)
Slightly Altered from a previous solution
您可以使用系统中的任何其他表来构建自己的动态日历/列表,该表至少具有与伪造行号所需的记录一样多的记录。下面的查询将使用MySQL @变量,其作用类似于内联程序和声明。我可以从给定的日期开始列表...例如您的2016-04-20,然后每次迭代,使用基于日期的函数添加1周。无需我知道或关心28、29(le年),30或31天有多少天。
“ AnyTableThatHasAtLeast156Records”下面的表引用就是这样。数据库中任何具有至少156条记录(每年52周,每年3年)的表
select
YEARWEEK( @startDate ) WeekNum,
@startDate as StartOfWeek,
@startDate := date_add( @startDate, interval 1 week ) EndOfWeek
from
( select @startDate := '2016-04-20') sqlv,
AnyTableThatHasAtLeast156Records
limit
156
这将为您提供156条记录的列表(假设您的“ anyTable…”一次具有全部156条记录。如果您需要将其连接到其他事务表,则可以通过创建上面的JOIN表来实现。在这里受益,因为我包括了开始日期和星期几,所以这些可以成为您加入表格的一部分。
示例,在
record WeekNum StartOfWeek EndOfWeek
1 ?? 2016-04-20 2016-04-27
2 ?? 2016-04-27 2016-05-04
3 ?? 2016-05-04 2016-05-11
4 ?? 2016-04-11 2016-05-18... etc
通过将1周添加到起点,您可以看到它将执行例:星期一至星期一。下面的JOIN条件比EndOfWeek还少。这将说明截至TOUP的所有交易,但不包括结束日期...例如2016-04-26 11:59:59 PM的交易(因此,比2016-04-27少,因为04/27是该交易的开始下周的交易周期)
select
Cal.WeekNum,
YT.YourColumns
from
YourTransactionTable YT
JOIN ( aboveCalendarQuery ) Cal
on YT.TransactionDate >= Cal.StartOfWeek
AND YT.TransactionDate < Cal.EndOfWeek
where
whatever else
如果您想要的话,甚至可以对分组依据(例如WeekNum)进行sum()。
希望这是一种构建日历以运行并链接到事务(如果需要)的更加准确和有效的方法。
回复评论。
您可以通过加入一个联接(选择1个联合选择2个联合...选择156),但是您可以选择。 “ AnyTable…”的唯一原因是,我敢肯定,使用任何具有事务处理的合理数据库,您都可以轻松拥有156条记录。唯一的目的是只允许一行在循环中循环以动态创建行。
比开始时遇到的循环机制还多得多的声音。没什么错,特别是学习目的,但是如果有更有效的方法,那更有意义吗?
每个来自评论的反馈
我不太清楚您要插入的另一个表,但是可以,您可以将其用于所有3000件事。提供更多您想做的事情,我可以进行调整...同时,类似这样的事情...
insert into YourOtherTable
( someField,
AnotherField,
WeekNum
)
select
x.someField,
x.AnotherField,
z.WeekNum
from
Your3000ThingTable x
JOIN (select
YEARWEEK( @startDate ) WeekNum,
@startDate as StartOfWeek,
@startDate := date_add( @startDate, interval 1 week ) EndOfWeek
from
( select @startDate := '2016-04-20') sqlv,
AnyTableThatHasAtLeast156Records
limit
156 ) z
on 1=1
where
x.SomeCodition...
通过加入1 = 1上的156条记录的选择(始终为true),它将为Your3000ThingTable中的任何记录返回156条记录。因此,如果您的库存项目表带有
Item Name
1 Thing1
2 Thing2
3 Thing3
您的最终插入内容将是
Item Name WeekNum
1 Thing1 1
1 Thing1 2
1 Thing1 ...
1 Thing1 156
2 Thing2 1
2 Thing2 2
2 Thing2 ...
2 Thing2 156
3 Thing3 1
3 Thing3 2
3 Thing3 ...
3 Thing3 156
要预先确认会发生什么,只需在1 = 1上尝试选择/联接,您将看到查询将要插入到目标表中的所有记录。