Как совместить значение ячейки с именем столбца с логикой CASE в SQL
У меня есть два ПРОСМОТРА, где данные представлены ниже:
ВИД 1
| username | function | level | location | |:-----------|------------:|:------------:| :-------------:| | John | Operation | Country | United Kingdom | | John | Operation | Area | South West | | John | Operation | Shop | 0001 |
ВИД 2
- JOIN запрос для извлечения нескольких столбцов, ссылающихся на один столбец из другой таблицы
- Как работать с несколькими JOIN в SQL Server
- Как ускорить Simple Join
- Заявление CASE в Join
- Реляционная алгебра и решение SQL
| shop | region | country | area | |:-----------|------------:|:---------------:| :-------------:| | 1200 | u1 | United Kingdom | West | | 1201 | u2 | United Kingdom | West | | 1000 | f1 | France | South West | | 1100 | i1 | Italy | South West | | 1111 | s1 | Spain | South West | | 1112 | n2 | Norway | South West | | 0001 | o1 | Japan | Asia |
Связь между двумя видами VIEW заключается в том, что каждая область AREA имеет более одной страны, каждая страна имеет более одного региона, каждый РЕГИОН имеет более одного магазина.
Попытка: Создать представление, где для каждого пользователя из данных верхней таблицы все строки будут генерироваться из нижней таблицы в зависимости от выбора LEVEL в верхней таблице. Поэтому в этом случае VIEW должен показать
Ожидаемый результат : Таким образом, в этом случае VIEW должен показать все МАГАЗИНЫ, РЕГИОНЫ, СТРАНЫ под AREA South West, все МАГАЗИНЫ и РЕГИОНЫ под СТРАНАМИ Великобритании и МАГАЗИН 0001.
| username | function | level | location | |:-----------|------------:|:---------------:| :-------------:| | John | Operation | shop | 0001 | | John | Operation | shop | 1001 | | John | Operation | shop | ... | | John | Operation | Country | United Kingdom| | John | Operation | Country | ... | | John | Operation | Country | ... | | John | Operation | Region | ... | | John | Operation | Region | ... | | John | Operation | Region | ... | | John | Operation | Area | South West | | John | Operation | Area | ... | | John | Operation | Area | ... |
Не знаете, как это можно сделать с помощью оператора CASE. Любая помощь будет оценена по достоинству.
- Как добавить строки для каждой даты?
- Производительность SQL с использованием JOIN вместо IN CLAUSE
- Присоедините две таблицы для всех возможных совпадений строк
- Присоедините 3 таблицы с 2, где предложения получают нулевые результаты
- Как обновить столбец таблицы Sql Server при соединении двух таблиц?
- SQL: Как показать столбец таблицы как строку?
- sql присоедините 2 таблицы к самой ранней дате после даты в первой таблице
- Относительная эффективность JOIN vs APPLY в Microsoft SQL Server 2008
Я думаю, для этого потребуется объединение четырех отдельных запросов:
- Первый запрос должен выбрать все магазины, равные или находящиеся в магазинах / регионах / странах / областях, указанных в первой таблице, которые присоединяются ко второй таблице.
- Второй запрос должен выбрать все регионы, равные или в регионах / странах / областях, указанных в первой таблице, которые присоединяются ко второй таблице.
- Третий запрос должен выбрать все страны, равные или в странах / областях, указанных в первой таблице, которые присоединяются ко второй таблице.
- Четвертый запрос должен выбрать все области, указанные в первой таблице, которые присоединяются ко второй таблице.
В каждом запросе могут быть дубликаты, поэтому мы должны использовать distinct
в каждом запросе для их устранения. Между запросами не может быть дубликатов, поэтому мы можем использовать union all
а не union
.
create table userop (username varchar(32), [function] varchar(32), level varchar(32), location varchar(32) ); create table shopgeo (shop varchar(32), region varchar(32), country varchar(32), area varchar(32) ); insert into userop (username,[function],level,location) values ('John','Operation','Country','United Kingdom'), ('John','Operation','Area','South West'), ('John','Operation','Shop','0001') ; insert into shopgeo (shop,region,country,area) values ('1200','u1','United Kingdom','West'), ('1201','u2','United Kingdom','West'), ('1000','f1','France','South West'), ('1100','i1','Italy','South West'), ('1111','s1','Spain','South West'), ('1112','n2','Norway','South West'), ('0001','o1','Japan','Asia') ; -- show base tables select * from userop; select * from shopgeo; -- solution select * from ( select distinct o.username, o.[function], 'shop' level, g.shop location from userop o inner join shopgeo g on o.location=case when o.level='Area' then g.area when o.level='Country' then g.country when o.level='Region' then g.region when o.level='Shop' then g.shop end union all select distinct o.username, o.[function], 'region' level, g.region from userop o inner join shopgeo g on o.location=case when o.level='Area' then g.area when o.level='Country' then g.country when o.level='Region' then g.region end union all select distinct o.username, o.[function], 'country' level, g.country from userop o inner join shopgeo g on o.location=case when o.level='Area' then g.area when o.level='Country' then g.country end union all select distinct o.username, o.[function], 'area' level, g.area from userop o inner join shopgeo g on o.location=case when o.level='Area' then g.area end ) t1 order by username, case when level='shop' then 1 when level='country' then 2 when level='region' then 3 when level='area' then 4 end, location;
Я сделал это несколько иначе
DECLARE @user varchar(50) = 'John' Declare @view1 table ( username varchar(50), ufunction varchar(50), ulevel varchar(50), location varchar(50)) INSERT INTO @view1 VALUES ('John', 'Operation', 'Country', 'United Kingdom') INSERT INTO @view1 VALUES ('John', 'Operation', 'Area', 'South West') INSERT INTO @view1 VALUES ('John', 'Operation', 'Shop', '0001') Declare @view2 table ( shop varchar(50), region char(2), country varchar(50), area varchar(50)) INSERT INTO @view2 VALUES ('1200', 'u1', 'United Kingdom', 'West') INSERT INTO @view2 VALUES ('1201', 'u2', 'United Kingdom', 'West') INSERT INTO @view2 VALUES ('1000', 'f1', 'France', 'South West') INSERT INTO @view2 VALUES ('1100', 'i1', 'Italy', 'South West') INSERT INTO @view2 VALUES ('1111', 's1', 'Spain', 'South West') INSERT INTO @view2 VALUES ('1112', 'n2', 'Norway', 'South West') INSERT INTO @view2 VALUES ('0001', 'o1', 'Japan', 'Asia') SELECT username, ufunction, v1.ulevel, location AS Shop, v2.region, v2.country, v2.area from @view1 v1 INNER JOIN @view2 v2 ON v1.location = v2.shop WHERE v1.ulevel = 'Shop' AND username = @user UNION SELECT v1.username, v1.ufunction, v1.ulevel, v2.shop, v2.region, v2.country, v2.area from @view1 v1 INNER JOIN @view2 v2 ON v1.location = v2.area WHERE v1.ulevel = 'Area' AND username = @user UNION SELECT v1.username, v1.ufunction, v1.ulevel, v2.shop, v2.region, v2.country, v2.area from @view1 v1 INNER JOIN @view2 v2 ON v1.location = v2.country WHERE v1.ulevel = 'Country' AND username = @user
РЕЗУЛЬТАТ
username ufunction ulevel Shop region country area John Operation Area 1000 f1 France South West John Operation Area 1100 i1 Italy South West John Operation Area 1111 s1 Spain South West John Operation Area 1112 n2 Norway South West John Operation Country 1200 u1 United Kingdom West John Operation Country 1201 u2 United Kingdom West John Operation Shop 0001 o1 Japan Asia
Идея состоит в том, что вы перечисляете все магазины только один раз, но в каждой записи вы можете прочитать, какое право дает пользователю доступ к этому магазину, будь то «Магазин», «Площадь» или «Страна»,