【问题标题】:sql stored procedure loopsql存储过程循环
【发布时间】:2011-01-04 21:33:25
【问题描述】:

我需要帮助在我的存储过程中构建一个循环,基本上我也希望它从 2005 年到今年循环。

 ALTER PROCEDURE [dbo].[testt1]
 as
DECLARE @YearToGet int;
SET @YearToGet = 2005;

WITH Years AS (
    SELECT DATEPART(year, GETDATE()) [Year]
    UNION ALL
    SELECT [Year]-1 FROM Years WHERE [Year]>@YearToGet
)

SELECT     TOP (100) PERCENT DIVISION, DYYYY, SUM(APRICE) AS Sales, SUM(PARTY) AS PAX, SUM(NetAmount) AS NetSales, SUM(InsAmount) 
                      AS InsSales, SUM(CancelRevenue) AS CXSales, SUM(OtherAmount) AS OtherSales, SUM(CXVALUE) AS CXValue
FROM         dbo.B101BookingsDetails AS B101BookingsDetails 


WHERE    Booked <= CONVERT(int,DateAdd(year, (SELECT * FROM Years) - Year(getdate()), DateAdd(day, DateDiff(day, 2, getdate()), 0)))
  and DYYYY = @YearToGet
GROUP BY  DYYYY, DIVISION

ORDER BY DIVISION,  DYYYY




OPTION (MAXRECURSION 0) -- this avoids hitting the recursion limit in the CTE

我真的可以使用一个存储过程网站,它比简单的选择语句更详细

【问题讨论】:

  • 我的循环不起作用,我想多次运行 select 语句,直到年份达到当前年份
  • 首先:为什么不直接使用YEAR(GETDATE()) 而不是奇怪的 DATENAME() 方法.....另外:你永远不会更新你的@YearToGetyear 值 - 我认为这会以非循环或无限循环结束......
  • 那么你真的想在这里做什么?尝试解释您要实现的目标.....仅从代码的 sn-p 就不清楚了....
  • 您遇到了什么错误?
  • 哦该死的哈哈我智障,我的主要问题是我在开始时遇到语法错误

标签: sql sql-server-2005 stored-procedures


【解决方案1】:

这不是直接的答案,但是代码不能以可读的方式在评论中发布,所以我认为这里应该没问题:

不要在 SP 中循环,而是使用 CTE 生成您需要的数字。

DECLARE @YearToGet int;
SET @YearToGet = 2005;

WITH Years AS (
    SELECT DATEPART(year, GETDATE()) [Year]
    UNION ALL
    SELECT [Year]-1 FROM Years WHERE [Year]>@YearToGet
)
SELECT * FROM Years -- join here with your query
OPTION (MAXRECURSION 0) -- this avoids hitting the recursion limit in the CTE

编辑:试试这个

WITH  Years
          AS (
              SELECT DATEPART(year, GETDATE()) [Year]
              UNION ALL
              SELECT [Year]-1
                FROM Years
                WHERE [Year] > @YearToGet
             )
    SELECT DIVISION, DYYYY, SUM(APRICE) AS Sales, SUM(PARTY) AS PAX, SUM(NetAmount) AS NetSales, SUM(InsAmount) AS InsSales, SUM(CancelRevenue) AS CXSales, SUM(OtherAmount) AS OtherSales, SUM(CXVALUE) AS CXValue
      FROM dbo.B101BookingsDetails 
      JOIN Years yr ON DYYYY = yr.[Year]
      WHERE Booked <= CONVERT(int, DATEADD(year, DYYYY-YEAR(GETDATE()), DATEADD(day, DATEDIFF(day, 2, GETDATE()), 0)))
      GROUP BY DYYYY, DIVISION
      ORDER BY DIVISION, DYYYY
    OPTION (MAXRECURSION 0);

【讨论】:

  • 所以我可以设置@year 来获取尽可能多的年数,而不是循环,但是明年它将如何更新
  • 只需将您的SELECT 语句与Years CTE 结合起来,如下所示,或者如果您愿意,可以做一个子查询(这几乎不需要对您的查询进行更改)。您当前的代码有缺陷,因为它会返回任意数量的结果集,这肯定不是您想要的。
  • 当你在做 SQL 时,总是在 SETS 中思考而不是逐行思考(大多数编程语言)。大多数(如果不是所有)SQL 循环都可以重写为仅使用 SQL。 SQL 中的循环会影响性能。
  • 感谢 clyc 的支持... ;-) - 此外,由于递归 CTE 的出现,动态生成用于集合操作的数据变得非常简单和高效.
  • 我同意一切,但简单的部分我什至无法加入我的声明
【解决方案2】:

好的,不使用递归 CTE :) 由于您已经将年份存储在 B101BookingsDetails 表中,因此只需从那里获取大于您正在查找的年份的年份列表。

CREATE PROCEDURE dbo.testt1
(
    @YearToGet int = 2005
)
AS

    WITH Years AS (
        SELECT DISTINCT DYYYY as year
        FROM    dbo.B101BookingsDetails
        WHERE DYYYY >= @YearToGet
    )   
    SELECT  TOP (100) PERCENT DIVISION, DYYYY, SUM(APRICE) AS Sales, SUM(PARTY) AS PAX, SUM(NetAmount) AS NetSales, 
                SUM(InsAmount) AS InsSales, SUM(CancelRevenue) AS CXSales, SUM(OtherAmount) AS OtherSales, SUM(CXVALUE) AS CXValue
        FROM    dbo.B101BookingsDetails 
                INNER JOIN Years
                    ON B101BookingsDetails.DYYYY = Years.Year
        WHERE   Booked  <= CONVERT(int,DateAdd(year, Years.Year - Year(getdate()), DateAdd(day, DateDiff(day, 2, getdate()), 0)))
        GROUP BY DYYYY, DIVISION

【讨论】:

  • 如果我想更改我的预订怎么办
【解决方案3】:

您需要在循环结束时增加@YearToGet。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-19
    • 1970-01-01
    • 2011-04-02
    • 1970-01-01
    相关资源
    最近更新 更多