将多个类似的查询合并为1

时间:2016-12-19 09:37:05

标签: python sql-server sqlalchemy

我在一些python代码中有以下查询,

    sel = select([staff.c.name,
                      staff.c.start_date,
                      staff.c.leave_allowance,
                      ]) \
            .select_from(staff) \
            .where(staff.c.name == request.args.get('user')) \
            .group_by(staff.c.name, staff.c.leave_allowance, staff.c.start_date)

        staff_member = ZS.db_connect().execute(sel).fetchone()
        staff_member = dict(staff_member)

sel1 = select([staff.c.start_date,
                func.sum(leave.c.hours).label('hours_taken')
                ]) \
        .select_from(join(staff, leave, (staff.c.name == leave.c.name))) \
        .where(leave.c.leave_start >= '2016-01-01') \
        .where(leave.c.leave_end <= '2016-03-30') \
        .where(leave.c.hr_status == 'RP_Approved') \
        .where(leave.c.name == request.args.get('user')) \
        .group_by(staff.c.name, staff.c.start_date)

        jan_user = ZS.db_connect().execute(sel1).fetchone()
        if(jan_user):
            jan_user = dict(jan_user)
            staff_member['JanMarTaken'] = jan_user['hours_taken']
        else:

            staff_member['JanMarTaken'] = 0

        sel2 = select([staff.c.start_date,
                func.sum(leave.c.hours).label('hours_taken')
                ]) \
            .select_from(join(staff, leave, (staff.c.name == leave.c.name))) \
            .where(leave.c.leave_start >= '2016-04-01') \
            .where(leave.c.leave_end <= '2016-09-30') \
            .where(leave.c.hr_status == 'RP_Approved') \
            .where(leave.c.name == request.args.get('user')) \
            .group_by(staff.c.name, staff.c.start_date)

        mar_user = ZS.db_connect().execute(sel2).fetchone()
        if(mar_user):
            mar_user = dict(mar_user)
            staff_member['MarSeptHours'] = mar_user['hours_taken']
        else:
            staff_member['MarSeptHours'] = 0


        sel2 = select([staff.c.start_date,
                func.sum(leave.c.hours).label('hours_taken')
                ]) \
            .select_from(join(staff, leave, (staff.c.name == leave.c.name))) \
            .where(leave.c.leave_start >= '2016-10-01') \
            .where(leave.c.leave_end <= '2016-12-31') \
            .where(leave.c.hr_status == 'RP_Approved') \
            .where(leave.c.name == request.args.get('user')) \
            .group_by(staff.c.name, staff.c.start_date)

        oct_user = ZS.db_connect().execute(sel2).fetchone()
        if(oct_user):
            mar_user = dict(mar_user)
            staff_member['OctDecHours'] = mar_user['hours_taken']
        else:
            staff_member['OctDecHours'] = 0

查询都基本上做同样的事情,即按名称搜索用户并检索某些日期之间记录的一些数据,我需要一年中3段的数据,所以目前我查询数据库3次使用不同的日期参数,有一种方法可以通过1个查询执行此操作,以获得更好的性能吗?

1 个答案:

答案 0 :(得分:0)

在SQL中执行此操作,以便您可以转换为存储过程,我在报告年度添加了一个变量@YearToCheck来传递。

让我们制作一些测试数据:

DECLARE @Staff TABLE
(
    Name VARCHAR(100),
    Emp_Start_Date DATETIME,
    Emp_End_Date DATETIME,
    Emp_Leave_Allowance INT
)

DECLARE @Leave TABLE
(
    Name VARCHAR(100),
    Leave_Start DATETIME,
    Leave_End DATETIME,
    Hr_Status VARCHAR(100)
)

DECLARE @YearToCheck INT = 2016

INSERT INTO @Staff 
( Name, Emp_Start_Date, Emp_End_Date, Emp_Leave_Allowance )
VALUES
( 'Fred', DATEFROMPARTS( 2016, 1, 3 ), NULL, 10 ),
( 'Wilma', DATEFROMPARTS( 2014, 2, 1 ), NULL, 10 ),
( 'Barney', DATEFROMPARTS( 2015, 7, 1 ), NULL, 10 ),
( 'Betty', DATEFROMPARTS( 2014, 2, 1 ), NULL, 10 );

INSERT INTO @Leave
( Name, Leave_Start, Leave_End, Hr_Status )
VALUES
( 'Fred', DATEFROMPARTS( 2015, 12, 1), DATEFROMPARTS( 2016, 6, 1), 'RP_Approved'),
( 'Fred', DATEFROMPARTS( 2016, 7, 1), DATEFROMPARTS( 2016, 8, 1), 'RP_Approved'),
( 'Wilma', DATEFROMPARTS( 2016, 1, 10), DATEFROMPARTS( 2016, 1, 15), 'RP_Approved'),
( 'Barney', DATEFROMPARTS( 2016, 6, 10), DATEFROMPARTS( 2016, 7, 10), 'RP_Approved'),
( 'Betty', DATEFROMPARTS( 2016, 7, 30), DATEFROMPARTS( 2016, 8, 5), 'RP_Approved'),
( 'Betty', DATEFROMPARTS( 2016, 9, 29), DATEFROMPARTS( 2016, 10, 3), 'RP_Approved'),
( 'Betty', DATEFROMPARTS( 2015, 1, 1), DATEFROMPARTS( 2017, 1, 5), 'RP_Approved');

现在让我们运行一个查询来查找不同的日期分区

第1节:1-1至&lt; 4-1(由于某种原因你有3/30,但3月31日结束了?)

第2节:4-1至&lt; 10-1

第3节:10-1至&lt; 1-1(明年)

SELECT s.Name,      
        CASE WHEN (l.Leave_Start <= DATEFROMPARTS( @YearToCheck, 4, 1)) AND (DATEFROMPARTS( @YearToCheck, 1, 1) <= l.Leave_End)  
            THEN
                DATEDIFF( DAY, 
                    CASE WHEN l.Leave_Start < DATEFROMPARTS( @YearToCheck, 1, 1) THEN DATEFROMPARTS( @YearToCheck, 1, 1) ELSE l.Leave_Start END,
                    CASE WHEN l.Leave_End > DATEFROMPARTS( @YearToCheck, 4, 1) THEN DATEFROMPARTS( @YearToCheck, 4, 1) ELSE DATEADD(DAY, 1, l.Leave_End) END ) --Inclusive
            ELSE 0
        END AS FirstSection,
        CASE WHEN (l.Leave_Start <= DATEFROMPARTS( @YearToCheck, 10, 1)) AND (DATEFROMPARTS( @YearToCheck, 4, 1) <= l.Leave_End)  
            THEN
                DATEDIFF( DAY, 
                    CASE WHEN l.Leave_Start < DATEFROMPARTS( @YearToCheck, 4, 1) THEN DATEFROMPARTS( @YearToCheck, 4, 1) ELSE l.Leave_Start END,
                    CASE WHEN l.Leave_End > DATEFROMPARTS( @YearToCheck, 10, 1) THEN DATEFROMPARTS( @YearToCheck, 10, 1) ELSE DATEADD(DAY, 1, l.Leave_End) END ) --Inclusive
            ELSE 0
        END AS SecondSection,
        CASE WHEN (l.Leave_Start <= DATEFROMPARTS( @YearToCheck + 1, 1, 1)) AND (DATEFROMPARTS( @YearToCheck, 10, 1) <= l.Leave_End)  
            THEN
                DATEDIFF( DAY, 
                    CASE WHEN l.Leave_Start < DATEFROMPARTS( @YearToCheck, 10, 1) THEN DATEFROMPARTS( @YearToCheck, 10, 1) ELSE l.Leave_Start END,
                    CASE WHEN l.Leave_End > DATEFROMPARTS( @YearToCheck + 1, 1, 1) THEN DATEFROMPARTS( @YearToCheck + 1, 1, 1) ELSE DATEADD(DAY, 1, l.Leave_End) END ) --Inclusive
            ELSE 0
        END AS ThirdSection
    FROM @Staff s
    INNER JOIN @Leave l
        ON l.Name = s.Name
    WHERE l.Hr_Status = 'RP_Approved'

以下是天数的输出数据:

Name    FirstSection    SecondSection   ThirdSection
Fred    91  62  0
Fred    0   32  0
Wilma   6   0   0
Barney  0   31  0
Betty   0   7   0
Betty   0   2   3
Betty   91  183 92

现在,我不会检查假期范围是否重叠,或者周日是否重叠等等......因为问题中没有,可以添加,但希望这是你可以使用从python中拉出逻辑并让sql server处理工作。