Можете ли вы сделать этот запрос быстрее?

0

В настоящее время я занимаюсь летней работой, и мне нужно расширить существующую программу.

Мой босс попросил меня сделать инструмент для наших клиентов, чтобы они могли видеть, сколько их сотрудников стоят в месяц. Но это не все. Дело в том, что у компании может быть одно или несколько "обществ" или подкомпаний. Мы хотим знать, сколько стоит сотрудник на общество в компании.

Это таблица, которую я использую:

  • общество: подкомпания с людьми, которая содержит имя и т.д. общества.
  • расписание: листы расписания, содержащие информацию о человеке и обществе.
  • люди: все люди или контакты в базе данных
  • paystate: содержит заработную плату для человека в течение определенного месяца.
  • накладные расходы: накладные расходы для человека за определенный месяц (обратите внимание, что дата - это строка (!), отформатированная следующим образом: YYYY-MM-DD)

Этот запрос работает, но выполнение занимает очень много времени. Есть ли способ сделать это быстрее?

Я выбираю год и месяц, получаю имя сотрудника (работника) и название общества. Затем я выбираю сумму минут работы сотрудника (для определенного общества). И, наконец, я вычисляю стоимость, проверяя его зарплату за этот месяц и накладные расходы за этот месяц.

SELECT
    YEAR(TS.assigndate) AS timesheet_year,
    MONTH(TS.assigndate) AS timesheet_month,
    CONCAT(TP.name, ' ', TP.firstname) AS worker,
    CONCAT(SP.name, ' ', SP.firstname) AS society,
    (
        SELECT
            SUM(timeunits) AS minutes
        FROM timesheet
        WHERE
            people_id = TP.id AND
            society_id = S.id AND
            MONTH(assigndate) = timesheet_month
    ) AS minutes,
    (
        SELECT (minutes / 60)
    ) AS hours,
    (
        SELECT(OO.hourtarif + SS.hourtarif) AS cost
        FROM salarystate SS, overhead OO
        WHERE
            people_id = TP.id AND
            YEAR(OO.date) = timesheet_year AND
            MONTH(OO.date) = timesheet_month AND
            CONVERT(SUBSTRING(SS.month FROM 1 FOR 4), UNSIGNED) = timesheet_year AND
            CONVERT(SUBSTRING(SS.month, -2), UNSIGNED) = timesheet_month
    ) AS cost,
    (
        SELECT (hours * cost)
    ) AS total_cost
FROM timesheet TS, society S, people SP, people TP
WHERE
    S.id = TS.society_id AND
    SP.id = S.people_id AND
    TP.id = TS.people_id
GROUP BY timesheet_year, timesheet_month, worker, society; 
  • 0
    Есть ли у вас индексы для некоторых столбцов таблицы базы данных?
  • 0
    Нет, и я не могу создать ни одного. Я не проектировал базу данных, и я не могу настроить ее тоже ...
Показать ещё 1 комментарий
Теги:

2 ответа

1
Лучший ответ

Теперь я использую временные таблицы, которые быстро развиваются, как ад:). Это код сейчас, если вам интересно:

CREATE TEMPORARY TABLE IF NOT EXISTS people_hours (
    people_id INTEGER NOT NULL,
    society_id INTEGER NOT NULL,
    year INTEGER NOT NULL,
    month INTEGER NOT NULL,
    hours DOUBLE NOT NULL,
    PRIMARY KEY(people_id, society_id, year, month)
);

CREATE TEMPORARY TABLE IF NOT EXISTS people_cost (
    people_id INTEGER NOT NULL,
    year INTEGER NOT NULL,
    month INTEGER NOT NULL,
    cost DOUBLE NOT NULL,
    PRIMARY KEY(people_id, year, month)
);

TRUNCATE people_hours;
TRUNCATE people_cost;

INSERT INTO people_hours (people_id, society_id, year, month, hours)
SELECT
    p.id as people_id,
    s.id as society_id,
    YEAR(t.assigndate) as year,
    MONTH(t.assigndate) as month,
    SUM(t.timeunits)/60 as hours
FROM people p, society s, timesheet t
WHERE
    t.society_id = s.id AND
    t.people_id = p.id
GROUP BY year, month, people_id, society_id;

INSERT INTO people_cost (people_id, year, month, cost)
SELECT
    p.id as people_id,
    YEAR(o.date) as cost_year,
    MONTH(o.date) as cost_month,
    SUM(o.hourtarif + s.hourtarif) as cost
FROM people p, salarystate s, overhead o
WHERE
    s.people_id = p.id AND
    CONVERT(SUBSTRING(s.month FROM 1 FOR 4), UNSIGNED) = YEAR(o.date) AND
    CONVERT(SUBSTRING(s.month, -2), UNSIGNED) = MONTH(o.date)
GROUP BY cost_year, cost_month, people_id;

SELECT 
    h.year,
    h.month,
    h.society_id,
    h.hours,
    c.cost,
    (h.hours * c.cost) AS total_cost,
    CONCAT(p.name, ' ', p.firstname) AS employee,
    CONCAT(ps.name, ' ', ps.firstname) AS society
FROM people_hours h, people_cost c, people p, people ps, society s
WHERE
    h.society_id = s.id AND
    h.people_id = p.id AND
    h.people_id = c.people_id AND
    s.people_id = ps.id AND
    h.year = c.year AND
    h.month = c.month
ORDER BY h.year, h.month, h.people_id, h.society_id;
  • 0
    Приятно видеть, что у вас есть решение, проблема с исходным запросом состоит в том, что вычисления подзапроса должны были выполняться для каждой строки, потому что они являются частью выбора, если вы находились в ситуации, когда вы не могли создать временные таблицы, которые могли бы иметь переписать запрос так, чтобы вы присоединились к подзапросу, перемещая часть where вашего подзапроса в состояние «on» объединения
2
  • 0
    Итак, я просто создаю временную таблицу с указанием часов и стоимости, а затем выполняю свои вычисления на этих таблицах?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню