【问题标题】:How to combine cell value to column name with CASE logic in SQL如何将单元格值与列名与 SQL 中的 CASE 逻辑结合起来
【发布时间】:2016-08-18 12:07:42
【问题描述】:

我有两个视图,其中数据表示如下:

查看 1

| username   |  function   |   level      | location       | 
|:-----------|------------:|:------------:| :-------------:|
| John       |   Operation |  Country     | United Kingdom | 
| John       |   Operation |  Area        | South West     |
| John       |   Operation |  Shop        | 0001           |

查看 2

| 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有多个Country,每个Country有多个REGION,每个REGION有多个店铺。

尝试:生成一个视图,根据顶部表格上的 LEVEL 选择,从顶部表格数据中为每个用户生成所有行将从底部表格生成。所以在这种情况下 VIEW 应该显示

预期结果:所以在这种情况下,视图应该显示 AREA South West 下的所有 SHOPS、REGIONS、COUNTRIES,COUNTRY United Kingdom 和 SHOP 0001 下的所有 SHOPS 和 REGIONS。

| 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 语句完成此操作。任何帮助,将不胜感激。

【问题讨论】:

  • 您应该至少完成了预期输出中的location 列。您应该首先弄清楚如何将两个视图连接在一起;我看不到这样做的简单方法。
  • 我有点疑惑。 In View 1 John 在 Country United Kingdom、Area South West 和 Shop 0001。 In View 2 Shop 0001 在日本,位于亚洲地区。英国在西部地区,而西南地区包括其他欧洲国家?
  • @JonathanWillcock 你是对的。可以访问 0001 商店意味着在结果中应该有 John 的一行,其中 Level 为 SHOP,位置为 0001。 VIEW 1 表示 John 可以访问 UK 下的所有商店、“SOUTH WEST 区域”下的所有国家、地区和商店" 以及恰好位于 COUNTRY japan、AREA asia 和 region o1 下的 SHOP 0001。这里AREA west下有其他国家,COUNTRY下有多个REGIONS,REGIONS下有SHOPS。

标签: sql-server sql-server-2008 join case


【解决方案1】:

我认为这需要四个独立查询的联合:​​

  • 第一个查询应选择等于或低于第一个表中指定的与第二个表连接的商店/地区/国家/地区的所有商店。
  • 第二个查询应选择等于或低于第一个表中指定的连接到第二个表的区域/国家/地区的所有区域。
  • 第三个查询应选择等于或低于第一个表中指定的与第二个表连接的国家/地区的所有国家/地区。
  • 第四个查询应选择第一个表中指定的与第二个表连接的所有区域。

每个查询中可能存在重复,因此我们应该在每个查询中使用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;

【讨论】:

  • 正如预期的那样。感谢您提供如此简单而有效的解决方案。
【解决方案2】:

我的做法略有不同

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

您的想法是您只列出所有商店一次,但在每条记录中您可以读取用户访问该商店的权限,无论是“商店”、“区域”还是“国家”

【讨论】:

    猜你喜欢
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-23
    • 1970-01-01
    • 2022-12-06
    • 1970-01-01
    相关资源
    最近更新 更多