Сотрудников маркировки, расходы которых близка к заложенной в бюджете суммы


Я работаю с базой данных SQLite. Это код, написанный лучший способ это может быть и правильно? Код:

  1. Выбирает из БД добавление столбца на процентную разницу между двумя столбцами

  2. Цикл по значениям столбцов

  3. Если дата в прошлом

  4. Если цена больше 500, а на разницу в процентном соотношении меньше, чем 1-ый аргумент установить флаг в 1

  5. Еще если цена меньше 500 и разница в процентах меньше, чем 2-й аргумент установить флаг в 1

  6. В противном случае держать флаг как 0

from datetime import datetime as dt

def calculateEmployeeSpend(read_cursor, flag_higher_amount, flag_lower_budget):

    read_cursor.execute("SELECT distinct b.employee_id, b.amount, "
                "s.spend, b.date, b.amount - s.spend as spend_left,  "
                "100.0*(b.amount - s.spend) / b.amount As PercentDiff FROM employee_budget_upload "
                "As b JOIN employee_budget_spent As s ON  b.employee_id = s.employee_id where b.amount != 0")

    for employee_id, amount, spend, date, spend_left, percent_diff in read_cursor:
        flag=0
        date_of_amount = dt.strptime(date, "%d/%m/%Y")
        if date_of_amount <= dt.now():
            if amount > 500 and percent_diff < int(flag_higher_amount) or amount < 500 and percent_diff < int(flag_lower_budget):
                flag=1

        write_cursor.execute('INSERT OR REPLACE INTO employee_overall_spend VALUES (?,?,?,?,?,?,?,?)',
                         (employee_id, amount, spend, date, spend_left, percent_diff, dt.now().strftime("%d/%m/%Y"), flag)) 


1440
5
задан 1 марта 2018 в 11:03 Источник Поделиться
Комментарии
2 ответа

Я бы сказала, что небольшой код, вы можете изменить пару вещей, чтобы сделать его немного более читабельным

Особенно часть с условные, это немного трудно следовать

date_of_amount = dt.strptime(date, "%d/%m/%Y")
if date_of_amount <= dt.now():
if amount > 500 and percent_diff < int(flag_higher_amount) or amount < 500 and percent_diff < int(flag_lower_budget):
flag=1

Можно попробовать взять все в мелких функциях:

is_past_amount_date = dt.strptime(date, "%d/%m/%Y") <= dt.now()
should_flag_amount = (amount > 500 and percent_diff < int(flag_higher_amount)) or (amount < 500 and percent_diff < int(flag_lower_budget))

if is_past_amount_date and should_flag_amount:
flag = 1

Также, старайтесь не использовать date в качестве переменной число, поскольку тени date название datetimeэто может иметь некоторые нежелательные последствия позже

Чтобы покончить с ней, исполнение курсор может иметь место за пределами функции, поэтому в качестве первого параметра вы получите employee_budget_cursors (что является результатом выполнения инструкции Select
Затем вы переходите в функцию напрямую

Также легче для тестирования

6
ответ дан 1 марта 2018 в 12:03 Источник Поделиться

Есть два пути вы можете пойти об этом. Придерживаться вашего текущего способом, или использовать SQL больше.

Нынешний способ


  • Я хотел бы изменить ваш цикл for, чтобы присвоить одно значение.

  • Я бы сделал функцию, которая говорит вам, если значения имеют флаг.

  • Я бы использовал *value для кортежа распаковать в write_cursor кортеж.

А так бы сделать что-то вроде:

from datetime import datetime as dt

def get_flag(employee_spend, higher, lower):
_, amount, _, date, _, percent_diff = employee_spend
return int(
dt.strptime(date, "%d/%m/%Y") <= dt.now()
and (
amount > 500
and percent_diff < int(higher)
or amount < 500
and percent_diff < int(lower)
)
)

def calculateEmployeeSpend(read_cursor, flag_higher_amount, flag_lower_budget):
higher, lower = int(flag_higher_amount), int(flag_lower_budget)

read_cursor.execute("SELECT distinct b.employee_id, b.amount, "
"s.spend, b.date, b.amount - s.spend as spend_left, "
"100.0*(b.amount - s.spend) / b.amount As PercentDiff FROM employee_budget_upload "
"As b JOIN employee_budget_spent As s ON b.employee_id = s.employee_id where b.amount != 0")

for employee_spend in read_cursor:
flag = get_flag(employee_spend, higher, lower)
write_cursor.execute(
'INSERT OR REPLACE INTO employee_overall_spend VALUES (?,?,?,?,?,?,?,?)',
(*employee_spend, dt.now().strftime("%d/%m/%Y"), flag)
)

Использовать SQL

Я не знаю SQL, но вы могли бы использовать что-то вроде:

CALCULATE_EMPLOYEE_SPEND_READ = '''\
DECLARE @curr_date DATETIME;
SET @curr_date = GETDATE();

SELECT
e.employee_id,
e.amount,
e.spend,
e.date,
e.spend_left,
e.percent_diff,
@curr_date as curr_date,
case when
e.date <= @curr_date
and (
e.amount > 500
and e.percent_diff < ?
or e.amount < 500
and e.percent_diff < ?
)
then 1
else 0
end
as flag
FROM (
SELECT distinct
b.employee_id,
b.amount,
s.spend,
b.date,
b.amount - s.spend as spend_left,
100.0 - 100.0*s.spend / b.amount as percent_diff
FROM employee_budget_upload As b
JOIN employee_budget_spent As s
ON b.employee_id = s.employee_id
WHERE b.amount != 0
) as e
'''
CALCULATE_EMPLOYEE_SPEND_WRITE = 'INSERT OR REPLACE INTO employee_overall_spend VALUES (?,?,?,?,?,?,?,?)'

def calculateEmployeeSpend(read_cursor, higher, lower):
read_cursor.execute(CALCULATE_EMPLOYEE_SPEND_READ, (int(higher), int(lower)))
for employee_spend in read_cursor:
write_cursor.execute(CALCULATE_EMPLOYEE_SPEND_WRITE, employee_spend)

8
ответ дан 1 марта 2018 в 01:03 Источник Поделиться