Sql 用于多年累计(YTM–年到月)测量的耗时循环的替代方案

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

我有一个问题,我一直试图解决了很长一段时间,现在我转向你。我有两个数据库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','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]]