Sql 用于多年累计(YTM–年到月)测量的耗时循环的替代方案
我有一个问题,我一直试图解决了很长一段时间,现在我转向你。我有两个数据库DB1和DB2以及我需要处理的数据的几个标准:Sql 用于多年累计(YTM–年到月)测量的耗时循环的替代方案,sql,pandas,Sql,Pandas,我有一个问题,我一直试图解决了很长一段时间,现在我转向你。我有两个数据库DB1和DB2以及我需要处理的数据的几个标准: ExcludeDates=['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04','2019-04-19','2019-04-22','2019-05-01','2019-05-31','2019-06-07','2019-12-21','2019-12-22','2019-12-23','2019-12-24','201
ExcludeDates=['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04','2019-04-19','2019-04-22','2019-05-01','2019-05-31','2019-06-07','2019-12-21','2019-12-22','2019-12-23','2019-12-24','2019-12-25','2019-12-26','2019-12-27','2019-12-28','2019-12-29','2019-12-30','2019-12-31']
Region = ['Region1','Region2', 'Region3', 'Region4', 'Region5', 'Region6']
months = [1,2,3,4,5,6,7,8,9,10,11,12]
现在,我想使用从DB1和DB2检索到的特性,对每个月累计的区域(即1月、1月、2月、1月、3月、1月、12月)进行大量计算
我最初的想法是在上面显示为1月、1月2日、1月3日、…、1月12日的年份的所有子集中循环,并在另一个循环中嵌套一个循环中的区域,该想法可行,但在某些情况下效率极低,执行时间长达10小时:
Measure_ytm = []
for RegionName in Region:
for month in months:
year = 2019
month = month
System = 'System1'
SystemV = 'System1V'
Query1 = """
select
a.feature1
,a.feature2
,a.feature3
from DB1 as a
inner join DateTable1 as cd on a.Date = cd.Date
inner join TimeTable as ct on A.Time = ct.Time
where 1=1
and a.feature6 = @System
and cd. Year = @year
and (cd.MonthOfYear between 1 and @month)
"""
new_query = query1.replace('@feature6', '\'' + System + '\'').replace('@year',
str(year)).replace('@month', str(month))
with pymssql.connect(server=server, user=user, password=password, database='BD1') as conn:
with conn.cursor(as_dict=True) as cursor:
cursor.execute(new_query)
all_rows = cursor.fetchall()
df1 = pd.DataFrame(all_rows)
query2 = """
select
b.Year as [Year]
,b.mon as [Month]
, a.TId as [SystemV]
,a.Name as [RegionName]
, v.Namn as [Description]
, m.Namn as [Type]
,b.Value
from DB2 as b
inner join MTable as m on b.MId=m.Id
inner join VTable as v on b.VId=v.Id
inner join AMTable as a on b.AMId=a.Id
where 1=1
and f.Year=@year
and (f.Mon between 1 and @month)
and b.TId=@SystemV
"""
query2 = query2.replace('@SystemV', '\'' + SystemV + '\'').replace('@year',
str(year)).replace('@month', str(month))
with pymssql.connect(server=server, user=user, password=password, database='DB2') as conn:
with conn.cursor(as_dict=True) as cursor:
cursor.execute(new_query)
all_rows = cursor.fetchall()
df2 = pd.DataFrame(all_rows)
### Follows a list of operations on the retrived dataframe df1 and df2 which result
x = <an array containing the YTM accumulated value, each value in the aray belonging to one Region>
Measure_ytm.append(x)
到
将1到@month之间的cd.MonthOfYear替换为列表中的cd.MonthOfYear,其中列表是每次传递时的列表,即,如果循环在传递5时,它将是[1,2,3,4,5],但这并不能解决问题。
现在,请注意:如果每次只花1个月的时间,那么需要在代码的pandas部分中完成的许多操作都可以在SQL查询部分中完成。对于所有区域和月份,整个代码运行需要20秒,因为DB1中大约有2500万行
因此,我的问题是:有没有更有效的方法?我猜应该是避免循环,但如何避免呢?我的经验是这种循环,在这种情况下应该避免,这证明我是对的。显然,在1到@month之间使用cd.MonthOfYear是问题的根源
感谢来自聪明人社区的任何帮助 添加了我的评论作为答案-请勾选是否有帮助。谢谢
看起来每个数据集只是每个月数据的并集,例如,Jan-Feb是Jan和Feb数据的并集。如果是这种情况,那么为什么不在整个一年(Jan-Dec)中运行一次查询,并将月份和地区作为列包含在select语句中呢。然后,您可以在代码中从此数据集中选择所需的记录,即仅在处理df1/df2时将循环放入代码中,而不是围绕SQL?看起来每个数据集只是每个月的数据的并集,例如,一月-二月是一月和二月的数据的并集。如果是这种情况,为什么不运行查询全年一次,即一月至十二月,并将月份和地区作为列包含在select语句中。然后,您可以在代码中从该数据集中选择所需的记录,即只在处理df1/df2时在代码中放置循环,而不是围绕SQL?它确实解决了“我的问题”。从10小时到2分钟。非常感谢。
months = [1,2,3,4,5,6,7,8,9,10,11,12]
months = [[1],[1,2],[1,2,3],[1,2,3,4],[1,2,3,4,5],[1,2,3,4,5,6],…..,[1,2,3,4,5,6,7,8,9,10,11,12]]