迭代过期Mysql循环

问题描述 投票:0回答:1

我写了一个存储过程,每周迭代三年。它不起作用,并返回一个模糊的错误消息。

#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

mysql loops stored-procedures
1个回答
2
投票

Slightly Altered from a previous solution

您可以使用系统中的任何其他表来构建您自己的动态日历/列表,该表至少具有假行数所需的记录数。下面的查询将使用MySQL @变量,其作用类似于内联程序和声明。我可以使用给定日期开始列表...例如2016-04-20然后每次迭代,使用基于日期的函数添加1周。我不需要知道或关心有多少天有28,29(闰年),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周,您可以看到它将执行Ex:星期一到星期一。我下面的JOIN条件比EndOfWeek少。这将解释任何交易,但不包括结束日期......例如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对group()进行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条记录的选择(总是如此),它将为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上的选择/加入,您将看到查询将插入目标表的所有记录。

© www.soinside.com 2019 - 2024. All rights reserved.