У меня две таблицы A и B:
Таблица - A - представляет основную информацию о лицах
emp_id | email | name
----------------------------------------
1 | [email protected] | john
2 | [email protected] | john1
3 | [email protected] | john2
4 | [email protected] | john3
5 | [email protected] | john4
Таблица - B представляет собой места, которыми управляют лица
john обрабатывает Регион и зона john1 обрабатывает территорию и территорию и так далее...
Последовательность locationType выглядит следующим образом: Region-> Зона → Area-> Территория Регионы имеет более высокий приоритет, а затем - зону и т.д.
id | emp_id | locationType
--------------------
1 | 1 | Region
2 | 2 | Area
3 | 3 | Area
4 | 4 | Territory
5 | 1 | Zone
6 | 2 | Territory
7 | 5 | Zone
8 | 5 | Area
Я хочу получить тех людей, которые обрабатывают более высокий тип locationType. Предположим, что john обрабатывает регион и зону, поэтому я хочу отобразить Регион, поскольку регион имеет более высокий приоритет, и аналогичным образом john1 обрабатывает территорию и область, поэтому я хочу отображать только Area, поскольку область имеет более высокий приоритет
Мой желаемый результат:
id | emp_id | name | locationType
----------------------------------------
1 | 1 | john | Region
5 | 5 | john4 | Zone
3 | 3 | john1 | Area
4 | 4 | john2 | Area
4 | 4 | john3 | Territory
Что я получаю
id | emp_id | name | locationType
----------------------------------------
1 | 1 | john | Region
1 | 1 | john | Zone
5 | 5 | john4 | Zone
5 | 5 | john4 | Area
2 | 2 | john1 | Area
3 | 3 | john2 | Area
4 | 4 | john3 | Territory
4 | 4 | john3 | Territory
Вы можете использовать field()
чтобы превратить места в числа. То, что вы хотите, - это минимальное местоположение, основанное на этом заказе.
Вы можете получить эту информацию для каждого сотрудника, используя коррелированный подзапрос:
select b.*
from b
where field(b.locationType, 'Region', 'Zone', 'Area', 'Territory') =
(select min(field(b2.locationType, 'Region', 'Zone', 'Area', 'Territory'))
from b b2
where b2.emp_id = b.emp_id
);
Добавление дополнительных столбцов из a
- это просто вопрос присоединения к таблице.
Используйте функцию FIELD
для преобразования строки в взвешенное число:
SELECT FIELD('Region', 'Region', 'Zone', 'Area', 'Territory') -- 1
SELECT FIELD('Zone', 'Region', 'Zone', 'Area', 'Territory') -- 2
SELECT FIELD('Area', 'Region', 'Zone', 'Area', 'Territory') -- 3
SELECT FIELD('Territory', 'Region', 'Zone', 'Area', 'Territory') -- 4
Затем вы можете найти минимум этого числа на сотрудника (меньшее число означает более высокий приоритет) и использовать функцию ELT
для преобразования числа обратно в строку:
SELECT ELT(1, 'Region', 'Zone', 'Area', 'Territory') -- Region
SELECT ELT(2, 'Region', 'Zone', 'Area', 'Territory') -- Zone
SELECT ELT(3, 'Region', 'Zone', 'Area', 'Territory') -- Area
SELECT ELT(4, 'Region', 'Zone', 'Area', 'Territory') -- Territory
Полный запрос:
SELECT table1.*, ELT(sq.location_sort, 'Region', 'Zone', 'Area', 'Territory') AS max_location
FROM table1
INNER JOIN (
SELECT emp_id, MIN(FIELD(locationType, 'Region', 'Zone', 'Area', 'Territory')) AS location_sort
FROM table2
GROUP BY emp_id
) AS sq ON table1.emp_id = sq.emp_id
Результат:
+--------+---------------+-------+--------------+
| emp_id | email | name | max_location |
+--------+---------------+-------+--------------+
| 1 | [email protected] | john | Region |
| 2 | [email protected] | john1 | Area |
| 3 | [email protected] | john2 | Area |
| 4 | [email protected] | john3 | Territory |
| 5 | [email protected] | john4 | Zone |
+--------+---------------+-------+--------------+
Чтобы решить проблему, просто выполните следующие действия. Это также поможет вам в нормализации данных.
1 Создайте новую таблицу с именем и идентификатором LocaitonType и укажите тип своего местоположения в том порядке, в котором вы хотите.
CREATE TABLE [dbo].[Table_C](
[LocationType_Id] [int] IDENTITY(1,1) NOT NULL,
[name] [nvarchar](50) NULL )
Insert Into [Table_C] (name) values('Region')
Insert Into [Table_C] (name) values('Zone')
Insert Into [Table_C] (name) values('Area')
Insert Into [Table_C] (name) values('Territory')
2.Alter your table b LocationType column Тип данных для int.
Alter Table Table_B
Alter column locationType int not null
Выберите Table_B.id, Table_A.emp_id, Table_A.name, Table_C.name как locationType из Table_B внутреннего соединения Table_A на Table_A.emp_id = Table_B.emp_id внутреннее соединение Table_C по таблице_C.LocationType_Id = Table_B.locationТип-порядок по таблице_C.LocationType_Id
использовать в case when
в порядке заказа
order by (case locationType when 'Region' then 1
when 'Zone' then 2
when 'Area' then 3
when 'Territory' then 4
else 5 end )