如何(SELECT)使用单个查询从两个表填充两个对象?

时间:2012-01-12 21:38:28

标签: sql ms-access select multiple-tables

这应该是程序员经常遇到的事情,但我从未尝试过这样的方式。

也就是说,我会解释。说,我需要从表Zoo中获取值,如下所示:

 @"SELECT z.predator, z.prey FROM Zoo AS z WHERE z.preyType=@carnivore"

现在我可以将所有值都添加到List中。我需要在网格中显示查询的详细信息。现在有了z.predator和z.prey值(这是为了时间整数,即它们各自的id),我需要填充其有意义的值,以便将它显示给最终用户(我不能只显示它们的ID )。所以现在我可以这样做:

 foreach (Zoo z in lstZoo)
 {
       Animal predator = GetFromAnimalTable(z.Predator)
       Animal prey = GetFromAnimalTable(z.Prey)
 }

这可能会使程序变慢。我可以一次查询所有细节吗?像这样:

   SELECT (SELECT * FROM ANIMAL WHERE id=z.predator), 
          (SELECT * FROM ANIMAL WHERE id=z.prey) 
   FROM Zoo AS z WHERE z.preyType=@carnivore

如果我可以将值读取到一个新的更大的对象?或者这被认为是一种不好的做法?

更新:执行此操作是标准做法吗?或者是否建议按照我先说的单独填充?

更新2 :我似乎犯了一个错误的错误,就是没有完全按照我的需要发布查询。我想我可以从这里调整答案以满足我的要求,不管是Access查询的括号构造。

以下是我的实际查询:

SELECT z.predator, p.lifeSpan, z.prey 
FROM Zoo AS z 
INNER JOIN Plants AS p ON p.parent_id=z.id 
WHERE z.preyType=@carnivore

实际上我已经在另一个表中进行了INNER JOIN查询。现在我需要得到(SELECT)z.predator的值(以及来自Animals表的相应值),p.lifeSpan,z.prey(及其对应的Animal表中的值)符合INNER JOIN和WHERE条件。

伪代码看起来像这样:

SELECT (SELECT * FROM ANIMAL WHERE id=z.predator), p.lifeSpan, (SELECT * FROM ANIMAL WHERE id=z.prey) 
FROM Zoo AS z INNER JOIN Plants AS p ON p.parent_id=z.id 
WHERE z.preyType=@carnivore

从这里的答案中扩展我的要求应该很容易,但直到现在都没有成功。我试过了:

SELECT a1.*, p.lifeSpan, a2.* 
FROM Zoo AS z 
INNER JOIN Plants AS p ON p.parent_id=z.id 
INNER JOIN Animal AS a1 ON (a1.id=z.predator)
INNER JOIN Animal AS a2 ON (a2.id=z.prey)
WHERE z.preyType=@carnivore

这个有和没有括号的许多变种。如何正确构建上述查询?

3 个答案:

答案 0 :(得分:4)

SELECT pred.col1 AS PredCol1, ..., pred.colx AS PredColx, 
       prey.col1 AS PreyCol1, ..., prey.colx AS PreyColx
    FROM Zoo z
        INNER JOIN Animal pred
            ON z.predator = pred.id
        INNER JOIN Animal prey
            ON z.prey = prey.id
    WHERE z.preyType = @carnivore

或者,您可能需要这样的东西。

SELECT 'Predator' AS AnimalType, pred.*
    FROM Zoo z
        INNER JOIN Animal pred
            ON z.predator = pred.id
    WHERE z.preyType = @carnivore
UNION ALL
SELECT 'Prey' AS AnimalType, prey.*
    FROM Zoo z
        INNER JOIN Animal prey
            ON z.prey = prey.id
    WHERE z.preyType = @carnivore

答案 1 :(得分:2)

这似乎是您最新的查询尝试:

SELECT a1.*, p.lifeSpan, a2.* 
FROM Zoo AS z 
INNER JOIN Plants AS p ON p.parent_id=z.id 
INNER JOIN Animal AS a1 ON (a1.id=z.predator)
INNER JOIN Animal AS a2 ON (a2.id=z.prey)";
WHERE z.preyType=@carnivore

从声明中删除分号。同时丢弃双引号。

为简化SQL,暂时不包括WHERE子句。

然后你应该处于更好的位置来解决Access'db引擎需要多个连接的括号问题。

SELECT a1.*, p.lifeSpan, a2.* 
FROM
    ((Zoo AS z 
    INNER JOIN Plants AS p ON p.parent_id=z.id) 
    INNER JOIN Animal AS a1 ON a1.id=z.predator)
    INNER JOIN Animal AS a2 ON a2.id=z.prey

注意我放弃了包含ON表达式的括号。简单的ON表达式不需要它们。如果你有一个ON的复合表达式,那么你需要这样的括号:

ON (p.parent_id=z.id AND p.foo = z.bar)

我建议的示例查询对我来说是正确的。 (如果它适用于您,请再次添加WHERE子句。)但是,我没有密切关注括号放置,因为我使用Access'查询设计器来设置连接...并且它添加了db引擎所需的括号。

我敦促你也这样做。如果您在没有安装Access副本的情况下使用来自Dot.Net的Access数据库,那么您真的应该获得一份副本。尝试使用没有该数据库的本机开发工具的数据库是一个不合理的挑战......有点像在戴连指手套时尝试打字。

答案 2 :(得分:1)

尝试加入表格

SELECT aPrey.Name as PreyName, aPredatior.Name as PredatorName 
FROM Zoo AS z 
LEFT JOIN Animal AS aPrey On aPrey.id= z.prey
LEFT JOIN Animal AS aPredatior On aPredatior.id= z.predator
WHERE z.preyType=@carnivore