2016-08-18 140 views
1

我有三个关系为GradParent(Country)> Parent(State)> Child(People)的表。我试图通过国家名称实现查询以获取以下情景和订单的独特信息。
1.所有人的数据与他们的国家和国家。
2.如果州没有人员,则州和国家数据。
3.如果没有国家和/或人民,那么只是国家数据。与多个外连接的SQL查询

表: enter image description here

SQL:

SELECT DISTINCT P1.ID as COUNTRY_ID, P1.NAME AS COUNTRY_NAME, P2.ID AS STATE_ID, 
P2.Name AS STATE_NAME , I1.ID AS PEOPLE_ID, I1.NAME AS PEOPLE_NAME 
FROM dbo.Country P1 
    INNER JOIN dbo.State P2 
     ON P2.Country_ID = P1.ID 
     INNER JOIN dbo.People I1 
      ON I1.Country_ID = P1.ID 

    <!-- WHERE P1.Name like 'USA%'--- optional--> 
    ORDER BY P1.NAME 
+1

试图改变你的'INNER JOIN's为'LEFT JOIN's – Shnugo

+0

像其他评论说/已经回答,你需要什么(生产与无状态的国家行,并没有为国家/国家我们会编辑它以反映出来,然后,你的数据模型没有被标准化(这不好),PEOPLE表只能有state_id;每个国家的国家已经显示在STATE表中,在PEOPLE中重复这些关系至多是多余的,最坏的情况是相互矛盾的,我认为这是某种功课;我不喜欢你的老师,他们用这样的表教坏习惯 – mathguy

+0

- 你的数据库产品是什么?你同时拥有SQL Server和Oracle,这实际上是正确的(只有两个)约1%的病例。 – mathguy

回答

1

使用LEFT OUTER连接。即使没有匹配的子记录,这些也会将信息保留在父表中。

此外,根据您的数据模型,您不应该需要DISTINCT关键字。毫无理由地抛出这种做法是不好的做法。

最后,您的加入条件PEOPLE需要限制STATE_ID

SELECT p1.id AS country_id, 
     p1.name AS country_name, 
     p2.id AS state_id, 
     p2.name AS state_name, 
     i1.id AS people_id, 
     i1.name AS people_name 
FROM dbo.country p1 
     LEFT JOIN dbo.state p2 ON p2.country_id = p1.id 
     LEFT JOIN dbo.people i1 ON i1.country_id = p1.id AND i1.state_id = p2.id 
-- WHERE P1.Name like 'USA%'--- optional-- 
ORDER BY p1.name, p2.name, i1.name 
+1

Nitpick ...为什么别名'p1'代表'国家','P2'代表'国家','I1'代表'人们'?为什么'''''''''国家'''''''国家','P'为'人'? :-)另外,连接条件'i1.country_id = p1.id'是多余的 - 一旦状态在'人'和'状态'之间正确匹配,并且国家在'国家'和'国家之间正确匹配','人民'和'国家'将自动匹配(或者表中包含内部矛盾 - 可怜的穷人,非正常设计的影响之一)。 – mathguy

+0

他没有发表餐桌设计。我不想假设state_id是State表中的主键,认为它很可能是。就表格别名而言,我使用了OP使用的内容。 –