【问题标题】:"Learn sql the hard way" - Exercise 13 : Trouble with a nested select statement"Learn sql the hard way" - 练习 13:嵌套 select 语句的问题
【发布时间】:2015-09-18 13:58:11
【问题描述】:

我正在学习“Learn SQL the hard way”,目前正在进行练习 13。

我被困在我们必须要做的部分

编写一个查询,可以找到所有宠物及其主人的名字 在 2004 年之后购买。关键是根据 宠物和父母的购买列。

我的桌子是这样的

sqlite> select * from person ; 
id          first_name  last_name   age         dead        phone_number  salary      dob       
----------  ----------  ----------  ----------  ----------  ------------  ----------  ----------
0           john        doe         20          0           9929          123123.0    2015-12-09
1           foo         bar         25          0           12            123123.0    2004-12-11
2           michal      jordan      19          0           12            123123.0    2005-12-11
3           tom         ford        30          0           12            123123.0    2002-12-11

还有

sqlite> select * from pet ; 
id          name        breed       age         dead        dob         parent_id 
----------  ----------  ----------  ----------  ----------  ----------  ----------
0           fluffy      Unicorn     5           0           2012-02-01            
1           quora       social net  10          0           2010-02-01            
2           Goldie      German She  6           0           2009-02-01            
3           boxer       golden ret  3           0           2007-02-01            
4           naman       kutta       10          1           2011-02-01            
5           hari        ohk         7           0           2015-02-01


sqlite> select * from person_pet ; 
person_id   pet_id      purchased_on
----------  ----------  ------------
2           2           2002-03-30  
2           3           2001-04-30  
2           4           2005-04-30  
2           5           2003-04-30  
3           1           2006-04-30  
3           4           2005-04-30    

我的schema 看起来像这样

sqlite> .schema
CREATE TABLE person(
 id INTEGER PRIMARY KEY, 
 first_name TEXT,
 last_name TEXT, 
 age INTEGER
, dead INTEGER, phone_number INTEGER, salary FLOAT, dob DATETIME);
CREATE TABLE pet(
 id INTEGER PRIMARY KEY, 
 name TEXT, 
 breed TEXT, 
 age INTEGER, 
 dead INTEGER
, dob DATETIME, parent_id INTEGER);
CREATE TABLE person_pet(
 person_id INTEGER, 
 pet_id INTEGER
, purchased_on DATETIME);
CREATE TABLE cars(
 id INTEGER PRIMARY KEY,
 car_name TEXT
);

我的尝试

我可以通过查询获得“2004”年之后的person_idpet_id

sqlite> select person_id, pet_id, purchased_on from person_pet 
   ...> where purchased_on > "2004-01-01" ;
person_id   pet_id      purchased_on
----------  ----------  ------------
2           4           2005-04-30  
3           1           2006-04-30  
3           4           2005-04-30

我现在应该如何继续把名字弄出来?

这是我第一次使用 SQL,因此非常感谢任何帮助。被困了一段时间。

编辑

我知道这可以使用 joins 来完成,但直到练习 13 才涉及到它。如果不使用 joins,我们怎么能做到这一点?

正如@vkp 在 cmets 中询问的那样,in 一直被覆盖到现在。

【问题讨论】:

  • join it to person table
  • 除了加入@vkp之外还有什么其他方式吗?
  • 您需要使用连接。这是一篇很好的文章来解释它们。 blog.codinghorror.com/a-visual-explanation-of-sql-joins/… 此外,您的表中的数据类型确实很差。您不应该使用文本,因为它自 sql server 2005 以来已被弃用,而支持 varchar(max)。但是对于名称,您应该找到一个合理的长度。此外,float 数据类型是一种近似数据类型,当您需要精确的精度时可能不应该使用。您应该改用数字。
  • 请只标记涉及的产品。 (MS SQL Server 和 SQLite 不完全兼容。)
  • @SeanLange 感谢您的意见。现在浏览博客。

标签: sql sqlite select


【解决方案1】:

你只需要join另外两个表。

select pp.person_id, pp.pet_id, pp.purchased_on, pt.name, p.first_name, p.last_name 
from person_pet pp
inner join person p on p.id = pp.person_id
inner join pet pt on pt.id = pp.pet_id
where purchased_on > "2004-01-01"

【讨论】:

  • 有效,但你能告诉我如何在不使用连接的情况下做到这一点吗?由于直到练习 13 才涵盖连接,所以必须有替代方法吗?非常感谢,但是!
  • in 被覆盖了吗?
  • 日期文字应该用单引号括起来,而不是双引号(尽管 SQLite 可能足够宽松以允许它)。
  • @vkp 是的。 in 已被覆盖。
  • @prodicus..我想不出不使用join 的方法。如果我能想到一个,我会尝试发布
【解决方案2】:

要将 ID 替换为相关名称,您可以使用 correlated subqueries

select (select first_name
        from person
        where id = person_pet.person_id),
       (select name
        from pet
        where id = person_pet.pet_id),
       purchased_on
from person_pet
where purchased_on >= '2005';

(当您需要从同一个表中获取多个列(例如,名字和姓氏)时,这比连接效率低。)

【讨论】:

  • 完美运行。我为列添加了别名,以使输出更清晰。你能指点我一些解释Correlated subqueries的博客/文章吗?
【解决方案3】:

虽然这是落后的,但至少可以说,它应该可以工作:

select person_id, (select max(first_name)+' '+max(last_name) from person where id = person_id) as person_name, pet_id, (select max(name) from pet where id = pet_id) as pet_name, purchased_on from person_pet 
   ...> where purchased_on > "2004-01-01" ;

PS - 使用 IN 将无济于事,因为您必须从两个额外的表中获取数据。如果它只是一个额外的桌子,它会工作得很好。

PPS - this 基本上是一个连接。也尝试使用它。

【讨论】:

  • 它为person_name 中的每个值显示0.0。你能再次检查查询@Mihai。非常感谢。
  • pet_name 中的值是否正常?
猜你喜欢
  • 2012-08-20
  • 1970-01-01
  • 1970-01-01
  • 2011-05-25
  • 2012-02-17
  • 2015-06-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多