简体   繁体   中英

SQL-Query on cascading tables

first of all I am using Linq and Entity Framework to create my queries.

I have 6 tables wich all depend on each other in a cascading way. So for the data layout in the tables looks like:

 Table 1: Id , Name
 Table 2: Id , Table1Id, Name
 Table 3: Id , Table2Id, Name 
 ...

Now I need to create a query where all of these results are joined and represent the cascade BUT I also need to keep the results where child elements are present. I do not know if this is understandable so here is an example:

Table 1:
1     Item1
2     Item2
3     Item3

Table 2:
1     1    Item1
2     1    Item2
3     2    Item3

Table 3:
1     1    Item1
2     3    Item2

Expected Queryresult:
Level1Id     Level1Name     Level2Id     Level2Name     Level3Id     Level3Name
________________________________________________________________________________
1            Item1          
1            Item1          1           Item1
1            Item1          1           Item1           1            Item1
1            Item1          2           Item2
2            Item2
2            Item2          3           Item3
2            Item2          3           Item3           2            Item2

The query-result does not need to exactly look like this but has to have the hirarchical order.

I have already tried to use an left-outer-join but this only provides the leaves of the expected result. the query looked like this:

var databaseLevel =
 (from lev1 in db.Level1
  from lev2 in db.Level2.Where(x => x.Level1Id == lev1.Id).DefaultIfEmpty()
  from lev3 in db.Level3.Where(x => (x.Level2Id == lev2.Id)).DefaultIfEmpty()
  from lev4 in db.Level4.Where(x => (x.Level3Id == lev3.Id)).DefaultIfEmpty()
  from lev5 in db.Level5.Where(x => (x.Level4Id == lev4.Id)).DefaultIfEmpty()
  from lev6 in db.Level6.Where(x => (x.Level5Id == lev5.Id)).DefaultIfEmpty()
  select new { Level1 = lev1, Level2 = lev2, Level3 = lev3, Level4 = lev4, Level5 = lev5, Level6 = lev6 }).AsQueryable();

The second approach I already tried was to union the results of the queries and add null values for Levels which are not used.

Query looks like:

var databaseLevel =
    (from lev1 in db.Level1s select new { Level1 = lev1, Level2 = (Level2s)null, Level3 = (Level3s)null, Level4 = (Level4s)null, Level5 = (Level5s)null, Level6 = (Level6s)null })
    .Concat(from lev2 in db.Level2s select new { Level1 = lev2.Level1s, Level2 = lev2, Level3 = (Level3s)null, Level4 = (Level4s)null, Level5 = (Level5s)null, Level6 = (Level6s)null })
    .Concat(from lev3 in db.Level3s select new { Level1 = lev3.Level2s.Level1s, Level2 = lev3.Level2s, Level3 = lev3, Level4 = (Level4s)null, Level5 = (Level5s)null, Level6 = (Level6s)null })
    .Concat(from lev4 in db.Level4s select new { Level1 = lev4.Level3s.Level2s.Level1s, Level2 = lev4.Level3s.Level2s, Level3 = lev4.Level3s, Level4 = lev4, Level5 = (Level5s)null, Level6 = (Level6s)null })
    .Concat(from lev5 in db.Level5s select new { Level1 = lev5.Level4s.Level3s.Level2s.Level1s, Level2 = lev5.Level4s.Level3s.Level2s, Level3 = lev5.Level4s.Level3s, Level4 = lev5.Level4s, Level5 = lev5, Level6 = (Level6s)null })
    .Concat(from lev6 in db.Level6s select new { Level1 = lev6.Level5s.Level4s.Level3s.Level2s.Level1s, Level2 = lev6.Level5s.Level4s.Level3s.Level2s, Level3 = lev6.Level5s.Level4s.Level3s, Level4 = lev6.Level5s.Level4s, Level5 = lev6.Level5s, Level6 = lev6 })
     .AsQueryable(); 

This query works just fine but has very poor performance. Now I do not have any other idea how to create my query...

Could someone please give me a hint?

For a table that I created (If you provide inserts with data I would translate it to exactly what you want the key is the with rollup and grouping function):

create table c1 (c1 varchar(20), c2 varchar(20), c3 varchar(20))

select case when (grouping(c1) =1 ) then ' ' else isnull(c1,' ') end as c1,
 case when (grouping(c2)=2) then ' ' else isnull(c2,' ') end as c2,
 case when (GROUPING(c3)=3) then ' ' else isnull(c3,' ') end as c3
    from c1 
group by c1,c2,c3 with rollup
order by c1,c2,c3 




Canada       
Canada  CT   
Canada  CT  Wilton
Canada  North    
Canada  North   Vancouver
Us       
Us  CT   
Us  CT  Wilton
Us  NJ   
Us  NJ  Brooklyn
Us  NJ  teaneck
Us  NY   
Us  NY  Brooklyn
Us  NY  NY

produced exactly what you wanted.

Your join would have to be this:

select * from 
table1 inner join table2 on [id]=table1id
 inner join table3 on table2id=table2.id

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM