简体   繁体   English

如何在SQL循环中循环,类似于for-each循环?

[英]How can I do loop within a loop in SQL, similar to a for-each loop?

I have poured over numerous questions and answers but can't seem to find a solution that works for me. 我倾注了许多问题和答案,但似乎无法找到适合我的解决方案。 Here is what I am trying to do: 这是我想要做的:

Say I have table called "Store" that holds Store IDs, store names, and the annual sales of that store. 假设我有一个名为“Store”的表,其中包含商店ID,商店名称以及该商店的年销售额。 The business wants each store to increase it's sales by 50% over the next year, and wants to calculate monthly target sales amounts that each store needs to reach to make the 50% increase value. 该公司希望每家商店在明年将其销售额增加50%,并希望计算每家商店需要达到的每月目标销售额,以使其增加50%的价值。 For example, if store number 5 had $1000 in sales last year, the target for the end of the next year would be $1500. 例如,如果5号店的销售额去年有1000美元,那么明年年底的目标就是1500美元。 And to reach that, the amount for each month would need to be something like $1042, $1084, $1126... $1500. 为达到这个目标,每个月的金额需要1042美元,1084美元,1126美元...... 1500美元。

What I am trying to do is insert 12 records for each store into a 'monthly plan fact' table. 我想要做的是将每个商店的12条记录插入“月度计划事实”表中。 I am trying to select a store from the Store table, grab the annual sales amount, then do a loop inside that where I calculate what each month value would be so I can insert it into the 'monthly plan fact' table, then select the next store from the store table... and so on. 我试图从Store表中选择一个商店,获取年度销售额,然后在我计算每月价值的内部循环,这样我就可以将其插入“月度计划事实”表中,然后选择从商店表中的下一个商店...依此类推。 As a C# developer, it seems a very simple task that could be accomplished with a 'for each' style loop with another 'for' loop inside it. 作为一个C#开发人员,这似乎是一个非常简单的任务,可以通过'for each'样式循环完成,其中包含另一个'for'循环。

But I cannot for the life of me figure out how to do this in SQL. 但我不能为我的生活弄清楚如何在SQL中做到这一点。 I know about temp tables, but I can't seem to figure out how to get multiple rows inserted into my 'monthly plan fact' table using the records from the Store table, and the values calculated in the loop to determine the monthly plan values. 我知道临时表,但我似乎无法弄清楚如何使用Store表中的记录将多行插入到我的'每月计划事实'表中,并在循环中计算的值来确定每月计划值。 I've read some on cursors, but it seems that most people advise against them in the SQL community, so I am at a loss on this one. 我已经阅读了一些关于游标的内容,但似乎大多数人都在SQL社区中反对他们,所以我对此感到茫然。

The T-SQL below shows how to really easily get the sales targets for each store for each month. 下面的T-SQL显示了如何真正轻松获得每个商店每个月的销售目标。 I've included two columns here: one called 'salesTargetYourExample' where we have a pattern like 1042, 1084, ... for sales targets and one called 'linearGrowthSales' where we have the new annual sales target (eg 1500 for the store that made 1000 last year) and simply look at what sales should be at the end of each month to reach that target assuming linear growth). 我在这里列出了两个列:一个名为'salesTargetYourExample',其中我们有一个类似1042,1084的模式,...用于销售目标,一个名为'linearGrowthSales',我们有新的年度销售目标(例如,商店为1500)去年做了1000个)并简单地看看每个月底应该达到的销售量,以达到该目标,假设线性增长)。

The short answer though is to always think in terms of sets and set based operations when working with databases. 简而言之,在使用数据库时总是要考虑集合和基于集合的操作。 Don't think in terms of loops 不要考虑循环

-- Create the store table
create table dbo.Store
(
    storeId int not null primary key clustered,
    storeName varchar(100) not null,
    annualSales money not null
);

-- Populate the data in the store table
insert into dbo.Store(storeId,storeName,annualSales)
values (1, 'My first store', 2000),
    (5, 'Store number five', 1000),
    (6, 'The sixth store', 2500);


-- Get the sales targets for each store on a monthly basis
select s.storeId, s.storeName, months.mth,
    (s.annualSales * 0.5 * months.mth/12) + s.annualSales as salesTargetYourExample,
    s.annualSales * 1.5 * months.mth/12 as linearGrowthSales
from dbo.Store as s
cross apply
(
    values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
) as months(mth)

In the event you choose to do a loop in SQL though its frowned upon but it does exist. 如果您选择在SQL中执行循环,尽管它不赞成但它确实存在。 Here is how its done. 这是它的完成方式。 This is a more general answer about loops in SQL not specific to this question. 这是一个关于SQL中不特定于此问题的循环的更一般的答案。 Im hoping someone who is stuck and for whatever reason cant go the other way (set based) can benefit: 我希望有人因为某种原因而陷入困境,不能以其他方式(以集合为基础)可以受益:

Declare @intCount as int
Declare @numberOfTimes as int

WHILE @intCount <= @numberoftimes

BEGIN

--Do something repetitive

END

In Sql you really should try to avoid using loops . Sql你真的应该尽量避免使用循环 Instead, you should use a set-based approach. 相反,您应该使用基于集合的方法。 This post (first answer) has a good link on why you shouldn't do it, then an example that could help you do it. 这篇文章 (第一个答案)有一个很好的链接,为什么你不应该这样做,然后一个例子,可以帮助你做到这一点。 Take a look at using a CURSOR instead. 看一下使用CURSOR

@paqogomez was right :) @paqogomez是对的:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM