与动态名称

时间:2015-12-04 20:02:55

标签: sql sql-server

我正在尝试连接两个引用表的结果,以获取引用不同表名的行值,这些行可由uuid选择。

我的表格如下:

表条目 表格地图 桌上的猫 桌狗

NR REFINT ID 命名 mapRef 品种 mapRef 品种
1 123 123 '狗' 456 '孟加拉' 123 '牧羊犬'
2 456 456 '猫' 888 'BIRMA' 999 '狮子狗'
3 789 789 '狗'
4 123

refInt条目引用了地图。 map的名称是对表的引用以及字段id,它也应用于表cat / dogs(动态表加载)。

// subset 1: list of numbers that needs to be loaded from entry table (1-4)
SELECT DISTINCT refInt FROM entry WHERE nr in (1,2,3,4)

// subset 2: get all names from map that have the same id like refInt from subset1
SELECT name FROM map WHERE id in subset1

// main query: load all rows from table with the given name
//             from map table that have the same mapRef value on it
SELECT * FROM (subset2.names) WHERE mapRef IN (subset2.ids)

结果应该是行:

1) 456 bengal
2) 123 sheepdog

我也提出了SQLFiddle

有没有办法将它与一个查询相结合?

2 个答案:

答案 0 :(得分:1)

它看起来像是:

SqlFiddle

select 
  sub.nr, 
  sub.breed
from (
    select e.nr, e.refInt, 
      case 
        when c.breed is not null then c.breed
        when d.breed is not null then d.breed
        else null
      end as breed
    from (
       select e.nr, e.refInt, m.name
       from entry e
       inner join map m on e.refInt = m.id
    ) e
    left join cats c on e.refInt = c.mapRef and e.name = 'cats'
    left join dogs d on e.refInt = d.mapref and e.name = 'dogs'
) sub
where sub.breed is not null

这在表现上会非常差。

现在IMO正确的架构将是:

table entry
nr refint
1  123
2  456
3  789
4  124 (duplicate?)

table breed
mapRef breed    species
123    sheepdog 1
999    poodle   1
456    bengal   2 
888    birma    2

table species
id  species
1   dogs
2   cats

这是标准化的,并且具有非常好的性能。

答案 1 :(得分:1)

请注意以下查询如何完全实现所需的结果集并完整演示表 cats dogs 如何真正只是分区单个实体 animals 。应该重新设计架构以反映这种新的理解。此查询也很有效,因为包含测试ID被推送到最内层CTE的深度,在读取实际表行的级别,而不依赖于引擎来发现这种潜在的优化(这可能是有问题的联合)。

with
cats2 as (
  select species='cat', mapref, breed
  from cats animals
  join entry on entry.refint = animals.mapref
  where entry.nr  in (1,2,3,4)
),
dogs2 as (
  select species='dog', mapref, breed
  from dogs animals
  join entry on entry.refint = animals.mapref
  where entry.nr  in (1,2,3,4)
),
animals as (
  select species, mapref, breed from cats2
  union all
  select species, mapref, breed from dogs2
)
select species, mapref, breed 
from animals
group by species, mapref, breed 

此测试脚本:

declare @entry table (nr int, refint int );
declare @map table (id int, name varchar(20) );
declare @cats table (mapRef int, breed varchar(20));
declare @dogs table (mapRef int, breed varchar(20));

insert @entry(nr,refint) values
     (1,123)
    ,(2,456)
    ,(3,789)
    ,(4,123);
insert @map(id,name) values
     (123,'dogs')
    ,(456,'cats')
    ,(789,'dogs');

insert @cats(mapRef,breed) values
    (456,'bengal'),(888,'burma');

insert @dogs(mapRef,breed) values
    (123,'sheepdog'), (999,'poodle');


with
cats2 as (
  select species='cat', mapref, breed
  from @cats animals
  join @entry entry on entry.refint = animals.mapref
  where entry.nr  in (1,2,3,4)
),
dogs2 as (
  select species='dog', mapref, breed
  from @dogs animals
  join @entry entry on entry.refint = animals.mapref
  where entry.nr  in (1,2,3,4)
),
animals as (
  select species, mapref, breed from cats2
  union all
  select species, mapref, breed from dogs2
)
select species, mapref, breed 
from animals
group by species, mapref, breed 

根据需要产生:

species mapref      breed
------- ----------- --------------------
cat     456         bengal
dog     123         sheepdog