如何修复这个简单的SQL查询?

如何修复这个简单的SQL查询?,sql,Sql,我有一个包含三个表的数据库: 用户表 国家表格 城市表 我想编写ANSI SQL,它将允许我获取所有用户数据(即用户详细信息,包括上一所学校的国家名称和他们现在居住的城市名称) 我遇到的问题是,我必须使用自连接,我有点困惑 模式如下所示: CREATE TABLE user_table (id int, first_name varchar(16), last_school_country_id int, city_id int); CREATE TABLE country_table (

我有一个包含三个表的数据库:

  • 用户表
  • 国家表格
  • 城市表
我想编写ANSI SQL,它将允许我获取所有用户数据(即用户详细信息,包括上一所学校的国家名称和他们现在居住的城市名称)

我遇到的问题是,我必须使用自连接,我有点困惑

模式如下所示:

CREATE TABLE user_table (id int, first_name varchar(16), last_school_country_id int, city_id int);

CREATE TABLE country_table (id int, name varchar(32));

CREATE TABLE city_table (id int, country_id int, name varchar(32));
这是我到目前为止提出的查询,但结果是错误的,有时,db引擎(mySQL)会问我是否要显示所有[此处的巨大数字]结果,这让我怀疑我无意中在某处创建了笛卡尔积

有人能解释一下这个SQL语句有什么问题吗?我需要做些什么来修复它

SELECT usr.id AS id, usr.first_name, ctry1.name as loc_country_name, ctry2.name as school_country_name, city.name as loc_city_name
                FROM user_table usr, country_table ctry1, country_table ctry2, city_table city
                WHERE usr.last_school_country_id=ctry2.id
                      AND usr.city_id=city.id
                      AND city.country_id=ctry1.id
                      AND ctry1.id=ctry2.id;

通常,如果要联接3个表,则会有两个联接语句。始终比要连接的项目数少1个

没关系,我明白你为什么需要加入, 我会继续在代码上工作

SELECT user_table.*, contry_table.*, city_table.* FROM user_table, country_table, city_table WHERE country_table.id = last_school_country_id AND city_id = city_table.id

通常,如果要联接3个表,则会有两个联接语句。始终比要连接的项目数少1个

没关系,我明白你为什么需要加入, 我会继续在代码上工作

SELECT user_table.*, contry_table.*, city_table.* FROM user_table, country_table, city_table WHERE country_table.id = last_school_country_id AND city_id = city_table.id

试试这个。为了清晰起见,我使用了
ANSI
语法编写了它。我假设您可能并不总是拥有
usr.city\u id
usr.last\u school\u country\u id
,因此我使用了
左外连接
,这意味着您将始终获得
usr
记录

我还删除了
和ctry1.id=ctry2.id
,因为这需要用户的当前城市与他们的
上一个学校/国家/地区id位于同一个国家/地区,我认为情况并非总是如此

SELECT usr.id AS id, usr.first_name, ctry1.name as loc_country_name, ctry2.name as school_country_name, city.name as loc_city_name 
FROM user_table usr
left outer join city_table city on usr.city_id=city.id 
left outer join country_table ctry1 on city.country_id=ctry1.id 
left outer join country_table ctry2 on usr.last_school_country_id=ctry2.id 

试试这个。为了清晰起见,我使用了
ANSI
语法编写了它。我假设您可能并不总是拥有
usr.city\u id
usr.last\u school\u country\u id
,因此我使用了
左外连接
,这意味着您将始终获得
usr
记录

我还删除了
和ctry1.id=ctry2.id
,因为这需要用户的当前城市与他们的
上一个学校/国家/地区id位于同一个国家/地区,我认为情况并非总是如此

SELECT usr.id AS id, usr.first_name, ctry1.name as loc_country_name, ctry2.name as school_country_name, city.name as loc_city_name 
FROM user_table usr
left outer join city_table city on usr.city_id=city.id 
left outer join country_table ctry1 on city.country_id=ctry1.id 
left outer join country_table ctry2 on usr.last_school_country_id=ctry2.id 

此查询选择城市与其上一所学校位于同一国家/地区的所有用户:

SELECT  usr.id AS id, usr.first_name, ctry1.name as loc_country_name, ctry2.name as school_country_name, city.name as loc_city_name
FROM    user_table usr
JOIN    city
ON      city.id = usr.city_id
JOIN    country_table ctry1
ON      ctry1.id = city.country_id
JOIN    country_table ctry2
ON      ctry2.id = usr.last_school_country_id
WHERE   ctry1.id = ctry2.id
它是原始查询的同义词

只要名为
id
的所有字段都是主键,此查询返回的记录数就不能超过
user\u表中的记录数

确保所有的
id
都是
主键,并且没有重复项

请运行以下查询:

SELECT  COUNT(*)
FROM    user_table

SELECT  COUNT(*), COUNT(DISTINCT id)
FROM    city

SELECT  COUNT(*), COUNT(DISTINCT id)
FROM    country_table

并将输出张贴在此处?

此查询选择其所在城市与其上一所学校位于同一国家/地区的所有用户:

SELECT  usr.id AS id, usr.first_name, ctry1.name as loc_country_name, ctry2.name as school_country_name, city.name as loc_city_name
FROM    user_table usr
JOIN    city
ON      city.id = usr.city_id
JOIN    country_table ctry1
ON      ctry1.id = city.country_id
JOIN    country_table ctry2
ON      ctry2.id = usr.last_school_country_id
WHERE   ctry1.id = ctry2.id
它是原始查询的同义词

只要名为
id
的所有字段都是主键,此查询返回的记录数就不能超过
user\u表中的记录数

确保所有的
id
都是
主键,并且没有重复项

请运行以下查询:

SELECT  COUNT(*)
FROM    user_table

SELECT  COUNT(*), COUNT(DISTINCT id)
FROM    city

SELECT  COUNT(*), COUNT(DISTINCT id)
FROM    country_table

然后在此处发布输出?

您确定
ctry1.id=ctry2.id
正确吗?您不需要自联接,也可以使用自联接,但它不会为您提供任何新的功能。你是说“必须使用自连接”,因为这是作业的一部分吗?@MJB:我的SQL可能已经生锈了,但我确实认为我需要一个自连接。原因是学校所在国家/地区和当前所在国家/地区(源自当前城市)可能不同。@Morphase:您能告诉我您希望查询返回什么吗?ctry1.id=ctry2.id对我来说毫无意义。虽然这不是您获得大量行的原因,但它应该只返回最后一个学校所在国家和城市所在国家相同的行。您确定
ctry1.id=ctry2.id
正确吗?您不需要自联接,也可以使用自联接,但它不会为您提供任何新内容。你是说“必须使用自连接”,因为这是作业的一部分吗?@MJB:我的SQL可能已经生锈了,但我确实认为我需要一个自连接。原因是学校所在国家/地区和当前所在国家/地区(源自当前城市)可能不同。@Morphase:您能告诉我您希望查询返回什么吗?ctry1.id=ctry2.id对我来说毫无意义。虽然这不是您获得大量行的原因,它应该只返回最后一个学校所在国家和城市所在国家相同的行。如果用户的最后一个学校在不同的国家,情况会怎样?@morphase:我不知道这些情况会怎样:我刚刚重写了您原来的查询。如果您不需要此筛选器,请删除
WHERE
子句。如果用户的上一所学校在不同的国家,情况会如何?@morphase:我不知道这些情况会如何:我只是重写了您原来的查询。如果您不需要此筛选器,请去掉
WHERE
子句。这是一个很好的示例。我终于有了一个具体的“连接”示例,这对我来说很有意义。我现在明白了。非常感谢。也谢谢你的解释。我已经接受了你的回答。这是一个很好的例子。我终于有了一个具体的“连接”示例,这对我来说很有意义。我现在明白了。非常感谢。也谢谢你的解释。我已经接受了你的回答。