#sql #sql-server
#sql #sql-server
Вопрос:
Я новичок в sql и изо всех сил пытаюсь сформировать запрос оптимизированным способом:
Предположим, что текущий финансовый год — 2020. Я хочу получить всех активных сотрудников вместе с сотрудниками, которые покинули организацию в период с 1 января 2020 года по 31 декабря 2020 года (с 2020-01-01 по 2020-12-31) (неактивный сотрудник).). Сотрудник, у которого нет date_of_leaving, считается активным сотрудником. Сотрудника, который покинул организацию до 2020-01-01, не должно быть в списке. Тестовые примеры:
- Если date_of_joining сотрудника = ‘2015-03-08’ и date_of_leaving = 2019-12-31 —> Неактивный сотрудник. он не должен быть в результате запроса.
- Если у сотрудника date_of_joining = ‘2015-03-08’ и date_of_leaving = null —> активный сотрудник. он должен быть в результате запроса.
- Если date_of_joining сотрудника = ‘2015-03-08’ и date_of_leaving = 2020-12-31 —> Неактивный сотрудник. он должен быть в результате запроса.
- Если date_of_joining сотрудника = ‘2015-03-08’ и date_of_leaving = 2020-01-19 —> Неактивный сотрудник. он должен быть в результате запроса.
Я хочу получить все следующие поля: contract_emp_id, offshore_emp_id, date_of_joining, date_of_leaving
может кто-нибудь помочь мне здесь написать оптимизированный sql-запрос.
Комментарии:
1. У вас есть рабочий «неоптимизированный SQL-запрос»?
Ответ №1:
выберите * из таблицы, где date_of_leaving = NULL или date_of_leaving >= ‘2020-01-01’
Ответ №2:
Попробуйте ниже:
SELECT * FROM employee WHERE date_of_joining >= '08-March-2015' AND (date_of_leaving IS NULL OR date_of_leaving >= '01-January-2020');
Если размер вашей таблицы слишком велик, рекомендуется создать некластеризованный индекс для обоих столбцов.
Ответ №3:
Вы должны использовать любые индексы, которые у вас есть в таблице, но без этой информации это хорошее предположение для повышения эффективности:
SELECT contract_emp_id, offshore_emp_id, date_of_joining, date_of_leaving
FROM yourTable
WHERE IsActive = 1
UNION ALL
SELECT contract_emp_id, offshore_emp_id, date_of_joining, date_of_leaving
FROM yourTable
WHERE IsActive = 0
AND date_of_leaving >= '20200101'
Как правило, я нахожу UNION ALL
, что с этим справляются лучше, чем OR
с оптимизатором.
Однако вы можете попробовать OR
и посмотреть, так ли быстро он возвращается в вашей среде, чтобы сохранить несколько строк кода, если хотите:
SELECT contract_emp_id, offshore_emp_id, date_of_joining, date_of_leaving
FROM yourTable
WHERE IsActive = 1
OR (IsActive = 0 AND date_of_leaving >= '20200101')
Ответ №4:
Приведенные выше запросы в порядке. Проблема заключается в том, хотите ли вы создать индекс для этого конкретного запроса. Помните, чем больше у вас индексов, тем медленнее будут вставки / обновления / удаления.
Вы хотите, чтобы ключи соответствовали предложению WHERE, включенные столбцы соответствовали столбцам, которые вы используете для поездки. Вероятно, вы захотите изменить это, чтобы другие подобные запросы могли использовать этот же индекс.
Вот индекс, который я бы рекомендовал для этого конкретного запроса.
CREATE NONCLUSTERED INDEX [IX_your_index_name]
ON [dbo].[Your_table] ([IsActive],[Date_of_joining])
INCLUDE ([contract_emp_id],[offshore_emp_id],[date_of_leaving])