将多个一对多关系合并到json-oracle-python中

将多个一对多关系合并到json-oracle-python中,python,sql,oracle,cx-oracle,Python,Sql,Oracle,Cx Oracle,(我知道这可以使用SQL炼金术来完成,但这也是一个学习练习,因此我了解在没有SQL炼金术之类的工具的情况下是如何完成的) 我的公司正在使用10.1 oracle数据库 数据库结构 主表(主键) 第二个表(外键与主键) 第三个表(外键与主键) 第二个表可以有0到4个链接项 第三个表可以有0-无限(但不可能有超过20个) 我的SQL查询运行良好,数据也很好。如果我们在其他表中得到多个条目,它只会返回具有相同主键的多行。似乎是标准的(对SQL来说是新的,所以我认为应该是这样) 问题是当我试图将数据处理

(我知道这可以使用SQL炼金术来完成,但这也是一个学习练习,因此我了解在没有SQL炼金术之类的工具的情况下是如何完成的) 我的公司正在使用10.1 oracle数据库

数据库结构 主表(主键) 第二个表(外键与主键) 第三个表(外键与主键)

第二个表可以有0到4个链接项 第三个表可以有0-无限(但不可能有超过20个)

我的SQL查询运行良好,数据也很好。如果我们在其他表中得到多个条目,它只会返回具有相同主键的多行。似乎是标准的(对SQL来说是新的,所以我认为应该是这样)

问题是当我试图将数据处理成一个单一的JSON条目,在所有内容上循环。以下是我目前的脚本:

cursor = conn.cursor()

    sql = """
        SELECT *
        FROM RC_CAL 
               join CALENDAR_EVENT 
                 ON RC_CAL.rc_id = CALENDAR_EVENT.rc_id
               left outer join CALENDAR_EVENT CALENDAR_EVENT_1 
                            ON RC_CAL.rc_id = CALENDAR_EVENT_1.rc_id 
               left outer join RC_HISTORY RC_HISTORY_1 
                            ON RC_CAL.rc_id = RC_HISTORY_1.rc_id
    """

    has_where = False
    params = {}
    query_conditions = []
    if is_active:
        has_where = True
        query_conditions.append('WHERE CALENDAR_EVENT.ACTIVE_YN = :ACTIVE')
        params['ACTIVE'] = is_active
    if env:
        env_string = 'AND CALENDAR_EVENT.env = :ENV' if has_where else 'WHERE CALENDAR_EVENT.env = :ENV'
        has_where = True
        query_conditions.append(env_string)
        params['ENV'] = env
    if from_date:
        from_string = 'AND CALENDAR_EVENT.end_dt >= :FROM_DATE' if has_where else 'WHERE CALENDAR_EVENT.end_dt >= :FROM_DATE'
        has_where = True
        query_conditions.append(from_string)
        params['FROM_DATE'] = from_date
    if to_date:
        to_string = 'AND CALENDAR_EVENT.end_dt <= :TO_DATE' if has_where else 'WHERE CALENDAR_EVENT.end_dt <= :TO_DATE'
        query_conditions.append(to_string)
        params['TO_DATE'] = to_date

    if len(query_conditions) > 0:
        sql += " ".join(query_conditions)

    cursor.execute(sql, **params)

    rows = cursor.fetchall()

    events = []
    for rcId, data in groupby(rows, key=lambda t: t[0]):
        rc_item = None
        generic_list = []
        history_list = []
        for item in data:
            if not rc_item:
                rc_item = EventModalV2(*item[0:11])
            generic_id = item[11]
            history_id = item[17]
            generic_data = item[11:17]
            history_data = item[17:]
            if not any(generic_id in generic_item for generic_item in generic_list) and generic_id:
                rc_item.update_with_generic(generic_data)
                generic_list.append(generic_data)
            if not any(history_id in history_item for history_item in history_list) and history_id:
                rc_item.update_with_history(history_data)
                history_list.append(history_data)
                
        events.append(rc_item)

    cursor.close()
    conn.close()

    return events
cursor=conn.cursor()
sql=”“”
挑选*
来自RC_CAL
加入日历活动
在RC_CAL.RC_id=CALENDAR_EVENT.RC_id上
左外部连接日历\u事件日历\u事件\u 1
在RC_CAL.RC_id=CALENDAR_EVENT_1.RC_id上
左外连接RC_历史RC_历史1
在RC_CAL.RC_id=RC_HISTORY_1.RC_id上
"""
has_where=False
参数={}
查询条件=[]
如果您处于活动状态:
have_where=True
query\u conditions.append('WHERE CALENDAR\u EVENT.ACTIVE\u YN=:ACTIVE')
params['ACTIVE']=处于活动状态
如果环境:
env_string='和CALENDAR_EVENT.env=:env'if has_where else'where CALENDAR_EVENT.env=:env'
have_where=True
查询条件.追加(环境字符串)
参数['ENV']=ENV
如果从以下日期开始:
from_string='和CALENDAR_EVENT.end_dt>=:from日期'if has_where else'where CALENDAR_EVENT.end_dt>=:from_日期'
have_where=True
查询\u条件.追加(从\u字符串)
参数['FROM_DATE']=FROM_DATE
如果截止日期:

正如Chris所建议的,首先找出减速发生的地方。根据您的发现,我有几个建议:

(1) 避免获取LOB值,因为这些值需要额外的往返来获取数据,从而减慢了过程。你可以看到一个例子


(2)如果前面的建议是不够的,你也可以考虑简单地获取三(四)个查询,并将它们放在Python中(使用DICT)。这样就不需要多次提取顶级行,然后删除重复的行。

添加检测以显示什么是慢的?查看SQL执行计划?
(170079, 3, 1, None, None, None, 'Test Demo Event - DS', 'N', 'N', None, datetime.datetime(2020, 11, 5, 19, 16, 22), 237247, datetime.datetime(2020, 11, 1, 4, 0), 'PROD', datetime.datetime(2020, 11, 1, 4, 0), 91, 'Y', 5051, <cx_Orac
le.LOB object at 0x00000237AE8954B8>, 'rc_create', datetime.datetime(2020, 11, 5, 19, 16, 22))


(170079, 3, 1, None, None, None, 'Test Demo Event - DS', 'N', 'N', None, datetime.datetime(2020, 11, 5, 19, 16, 22), 237247, datetime.datetime(2020, 11, 1, 4, 0), 'PROD', datetime.datetime(2020, 11, 1, 4, 0), 91, 'Y', 5052, <cx_Orac
le.LOB object at 0x00000237AE895580>, 'rc_patch', datetime.datetime(2020, 11, 5, 19, 17, 7))


(170079, 3, 1, None, None, None, 'Test Demo Event - DS', 'N', 'N', None, datetime.datetime(2020, 11, 5, 19, 16, 22), 237247, datetime.datetime(2020, 11, 1, 4, 0), 'PROD', datetime.datetime(2020, 11, 1, 4, 0), 91, 'Y', 5053, <cx_Orac
le.LOB object at 0x00000237AE895648>, 'rc_patch', datetime.datetime(2020, 11, 5, 19, 17, 59))


(170079, 3, 1, None, None, None, 'Test Demo Event - DS', 'N', 'N', None, datetime.datetime(2020, 11, 5, 19, 16, 22), 237247, datetime.datetime(2020, 11, 1, 4, 0), 'PROD', datetime.datetime(2020, 11, 1, 4, 0), 91, 'Y', 5054, <cx_Orac
le.LOB object at 0x00000237AE895710>, 'rc_patch', datetime.datetime(2020, 11, 5, 19, 19, 9))