共享层次结构复制和LEFT JOIN

时间:2016-07-24 23:55:59

标签: sql sqlite

我们假设我只能在SQLite中执行此操作。

我有两张桌子。

State {
  DistrictID: int
  SubdistrictID: int
  CityID: Int
  name: varchar(36)
}

在州表中显然是一个明显的层次结构。一个州有多个区,每个区都有一些分区,每个分区都有一些城市。

另一张表是一个城市的学生人数,其中Students.CityID = State.CityID

Students {
  CityID: int
  number: int
}

我想知道一个区内现有的学生人数' 221'

QUERY SELECT sum(students.number) from State LEFT JOIN Students students ON State.CityID = students.CityID WHERE State.DistrictID = 221 GROUP BY State.DistrictID

到目前为止,这确实有效。我得到了来自221区所有城市的学生总数。

继承人的并发症。

某些城市在子区域之间共享。在这种情况下,一个区有一个城市在两个分区之间共享。这反映在州表中。

State Table
Row0: DistrictID: 221; SubDistrictID: 332; CityID: 554
Row1: DistrictID: 221; SubDistrictID: 332; CityID: 555
Row2: DistrictID: 221; SubDistrictID: 333; CityID: 554
Row3: DistrictID: 221; SubDistrictID: 333; CityID: 557

第0行和第2行在两个分区(332和333)之间共享同一个城市(554)。

在这种情况下,上面的sql查询会将SUM()值加倍,因为同一城市的数量是TWICE。

如何通过不改变表的架构来解决由于技术错误但却是现实问题而在逻辑上出现的复杂复制?我尝试使用distinct,但它并不适合这个目的,因此不起作用。

2 个答案:

答案 0 :(得分:1)

在执行select distinct之前,您可以使用join获取区内每个城市的一个引用:

select sum(s.number)
from (select distinct cityid
      from state
      where destrictid = 21
     ) c left join
     students s
     on s.cityid = c.cityid

答案 1 :(得分:0)

Sum会添加所有Student.Numbers。如果您想要学生人数,请使用count。为了给你一个想法,如果该区有2名学生,其中一名学生Student.number 1而另一名学生Student.Number 4,sum将返回5,count将返回2:

select sum(S.number) 
from Students S inner join State St on S.CityId = St.CityId 
where St.DistrictID = 221 

由于您正在寻找单个DistrictId,因此您不需要group by districtId。此外,我使用的是inner join,因为您只希望CityId表中有State的学生。

编辑:

您可以按如下方式加入其他表:

select D.DistrictName, sum(S.number) 
from Students S inner join State St on S.CityId = St.CityId 
inner join City C on St.CityId = C.Id
inner join District D on St.DistrictId = D.DistrictId
where St.DistrictID = 221 
group by D.DistrictName