如何遍历存储过程中的表?
Posted
技术标签:
【中文标题】如何遍历存储过程中的表?【英文标题】:How can I loop through a table within a stored procedure? 【发布时间】:2017-03-27 21:14:39 【问题描述】:这个问题是从this one演变而来的。
我有两张表需要查询并从中收集一些计算得出的总和;我需要一个基于单位的结果集——每个单位一行,为它们计算的数据折叠到该行中。
这两个表包含以下相关成员:
客户类别日志:
Unit varchar(25)
MemberNo varchar(10)
Category varchar(50)
Subcategory varchar(50)
BeginDate Datetime
EndDate Datetime
ReportingMonthlySales:
Unit (VarChar)
MemberNo (VarChar)
MonthlySales (Money)
CYear (Int)
Cmonth (Int)
对于每个 Unit(在两个表中都有很多行,每个 MemberNo 一个,但在结果集中包含一行),我需要填充四列:New、Assumed、Existing 和 Organic。这些值是基于属于相应“子类别”字段的单元的所有成员的总和。 CustomerCategoryLog 表的 BeginDate/EndDate 值用于确定单位/成员在被评估的月/年期间属于哪个子类别。
所以结果集的简化形式如下所示:
Unit New Assumed Existing Organic Total
---- --- ------- -------- ------- -----
Abuelos $22 $44 $33 $11 $110
Gramps $12 $23 $1 $34 $70
. . .
用英语来表达这个问题是这样的:
给定用户作为参数提供的月份和年份(例如“1”代表月份(一月)和“2016”代表年份),找出每个 Unit 在 MonthlySales 中每个该月内的子类别(其中 BeginDate 小于或等于用户提供的月/年日期并且 EndDate 大于或等于提供的月/年日期)。
所以看来我需要从年/月参数中创建一个日期,以便与 CustomerCategoryLog 表中的 BeginDate 和 EndDate 值进行比较(另一种选择是更改 CustomerCategoryLog 表,使其具有 BeginDateMonth, BeginDateYear、EndDateMonth 和 EndDateYear 整数;但我认为必须有一种直接的方法来根据提供的年/月参数创建日期。
我的问题是如何在 TSQL 中实际构建它。我不是 SQLhead,我最好的(伪sql)刺是:
DECLARE @Unit varchar(30);
DECLARE @Year Int;
DECLARE @Month Int;
. . .
DECLARE @PARAMDATE DATETIME = (Year + Month + 01).ToDateTime();
SELECT DISTINCT UNIT INTO #UNITS U FROM ReportingMonthlySales
WHILE NOT U.EOF DO
Unit = U.Unit
SELECT Unit, MonthlySales as 'NewSales' FROM (SELECT MonthlySales FROM ReportingMonthlySales RMS left join
CustomerCategoryLog CCL on RMS.Unit = CCL.Unit WHERE RMS.Unit = Unit AND RMS.CYear = @Year and RMS.CMonth = @Month
AND CCL.BeginDate >= PARAMDATE AND CCL.EndDate <= PARAMDATE AND CCL.Subcategory = 'New'),
MonthlySales as 'AssumedSales' FROM (SELECT MonthlySales FROM ReportingMonthlySales RMS left join
CustomerCategoryLog CCL on RMS.Unit = CCL.Unit WHERE RMS.Unit = Unit AND RMS.CYear = @Year and RMS.CMonth = @Month
AND CCL.BeginDate >= PARAMDATE AND CCL.EndDate <= PARAMDATE AND CCL.Subcategory = 'Assumed'),
MonthlySales as 'ExistingSales' FROM (SELECT MonthlySales FROM ReportingMonthlySales RMS left join
CustomerCategoryLog CCL on RMS.Unit = CCL.Unit WHERE RMS.Unit = Unit AND RMS.CYear = @Year and RMS.CMonth = @Month
AND CCL.BeginDate >= PARAMDATE AND CCL.EndDate <= PARAMDATE AND CCL.Subcategory = 'Existing'),
MonthlySales as 'OrganicSales' FROM (SELECT MonthlySales FROM ReportingMonthlySales RMS left join
CustomerCategoryLog CCL on RMS.Unit = CCL.Unit WHERE RMS.Unit = Unit AND RMS.CYear = @Year and RMS.CMonth = @Month
AND CCL.BeginDate >= PARAMDATE AND CCL.EndDate <= PARAMDATE AND CCL.Subcategory = 'Organic')
FROM ReportingMonthlySales RMS2
ORDER BY RMS2.Unit
END WHILENOTEOF
我知道这不太正确,甚至可能不太正确,但希望对于 SQL 专家/jr 来说已经足够清楚了。读心者,以了解我需要做什么/正在尝试做什么。
更新
以下是查询的两个表中的一些示例数据:
CustomerCategoryLog 表:
MemberNo = 007
Unit = AMC THEATERS
Subcategory = New
BeginDate = 1/1/2016
EndDate = 12/31/2016
MemberNo = 029
Unit = FOODBUY HMS
Subcategory = Existing
BeginDate = 1/1/2015
EndDate = 12/31/2015
ReportingMonthlySales 表:
Unit = AMC THEATERS
MemberNo = 007
MonthlySales = $988.82
CYear = 2016
Cmonth = 1
Unit = FOODBUY HMS
MemberNo = 029
MonthlySales = $61,479.28
CYear = 2017
Cmonth = 3
【问题讨论】:
真正有用的是关于您的表格的一些细节。这是一个很好的起点。 spaghettidba.com/2015/04/24/…你发的那个查询是一堵文字墙,让我的眼睛流血了。 您需要哪些具体细节? 你看我贴的链接了吗?诸如表名、列名、数据类型、示例数据之类的东西。你知道……那种可以回答的细节。 “其中 BeginDate 大于或等于月/年日期且 EndDate 小于或等于月/年日期)。”这是倒退还是我没有正确阅读? @SeanLange:上面的所有东西不都是 - 两个表名和它们的列吗?好的,我将添加一些示例数据... 【参考方案1】:这看起来像是很长的路要走。
这样的事情怎么样?
declare @Unit varchar(30);
declare @Year int;
declare @Month int;
declare @paramdate datetime = datefromparts(@year, @month, 1);
/* --prior to sql server 2012
declare @paramdate datetime;
set @paramdate = convert(datetime,convert(char(4),@Year)
+right('0'+convert(varchar(2),@month),2)
+'01')
*/
select distinct unit
into #Units
from ReportingMonthlySales;
select
u.Unit
, New = sum(case when ccl.Subcategory = 'New' then rms.MonthlySales else 0 end)
, Assumed = sum(case when ccl.Subcategory = 'Assumed' then rms.MonthlySales else 0 end)
, Existing = sum(case when ccl.Subcategory = 'Existing' then rms.MonthlySales else 0 end)
, Organic = sum(case when ccl.Subcategory = 'Organic' then rms.MonthlySales else 0 end)
from #Units u
left join CustomerCategoryLog ccl
on u.Unit = ccl.Unit
and @paramdate >= ccl.begindate
and @paramdate <= ccl.enddate
left join ReportingMonthlySales rms
on u.Unit = rms.Unit
and rms.cyear = @year
and rms.cmonth = @month
group by u.unit;
【讨论】:
谢谢;这看起来很有希望,但我收到“错误 102:'U' 附近的语法不正确”。这里:进入#Units U @B.ClayShannon 在into #Units
之后删除U
。我在重塑你的伪代码时错过了这一点。
酷;它似乎有效;它不返回任何数据,但我认为这是一个数据问题...我会尝试其他一些 args/param vals。
添加到 CustomerCategoryLog 的最后一条记录始终未设置 EndDate (null),因此我不得不将第二个日期检查更改为此:并且 @paramdate
@B.ClayShannon 啊,这是有道理的。很高兴你成功了!以上是关于如何遍历存储过程中的表?的主要内容,如果未能解决你的问题,请参考以下文章