Sql 需要在只返回一行的外部联接中创建表达式

Sql 需要在只返回一行的外部联接中创建表达式,sql,correlated-subquery,Sql,Correlated Subquery,我正在创建一个非常复杂的动态sql,它必须为每个用户返回一行,但现在我必须针对一对多表进行连接。我执行外部联接以确保至少返回一行,并可以检查null以查看该表中是否有数据,但如果该用户的第二个表中有多行,我必须确保仅从该外部联接部分返回一行。 到目前为止,我已经想到了这个:sybase SELECT a.user_id FROM table1 a ,table2 b WHERE a.user_id = b.user_id AND a.sub_id = ( SELECT min(c

我正在创建一个非常复杂的动态sql,它必须为每个用户返回一行,但现在我必须针对一对多表进行连接。我执行外部联接以确保至少返回一行,并可以检查null以查看该表中是否有数据,但如果该用户的第二个表中有多行,我必须确保仅从该外部联接部分返回一行。 到目前为止,我已经想到了这个:sybase

SELECT a.user_id
FROM table1 a
    ,table2 b
WHERE a.user_id = b.user_id
AND a.sub_id = (
    SELECT min(c.sub_id)
    FROM table2 c
    WHERE b.sub_id = c.sub_id
    )
子查询在一对多表中查找该特定用户的最小值

这是可行的,但当表1和表2变得非常大时,我担心进行相关子查询会带来麻烦。 有更好的办法吗?我正试着想出一个办法让会员们参与进来,但我看不到。
另外,如果rowcount=1或top 1对我没有帮助,因为我没有尝试修复上述查询,我只是将上述内容添加到一个已经很复杂的查询中。

也许您的示例过于简化,但我会使用以下组:

SELECT a.user_id FROM table1 a LEFT OUTER JOIN table2 b ON (a.user_id = b.user_id) GROUP BY a.user_id 我担心唯一的其他方法是使用嵌套查询:

此查询与示例之间的区别在于“子表”只生成一次,但是在示例中,您为表1中的每一行生成了一个“子表”,但这可能取决于编译器,因此您可能希望使用查询分析器检查性能

SELECT a.user_id, b.sub_id FROM table1 a LEFT OUTER JOIN ( SELECT user_id, min(sub_id) as sub_id, FROM table2 GROUP BY user_id ) b ON (a.user_id = b.user_id) 另外,如果您的查询变得非常复杂,我会使用临时表来简化代码,这可能会增加一些处理时间,但会使您的查询更易于维护

临时表示例如下:

SELECT user_id INTO #table1 FROM table1 WHERE ..... SELECT a.user_id, min(b.sub_id) as sub_id, INTO #table2 FROM #table1 a INNER JOIN table2 b ON (a.user_id = b.user_id) GROUP BY a.user_id SELECT a.*, b.sub_id from #table1 a LEFT OUTER JOIN #table2 b ON (a.user_id = b.user_id) 那么:

select a.user_id 
from table1 a
where exists (select null from table2 b 
              where a.user_id = b.user_id 
             )

在MySql中,您可以使用

select *
from foo
where bar = 1
limit X;

不幸的是,我相当肯定这是一个特定于MySQL的SQL扩展。然而,谷歌搜索mysql sybase limit之类的东西可能会发现sybase的等价物。

首先,我相信您尝试编写的查询是:

select a.user_id 
from table1 a, table2 b 
where a.user_id = b.user_id 
and b.sub_id = (select min(c.sub_id) 
                from table2 c 
                where b.user_id = c.user_id)
除了你想要一个外部连接,我想有人删掉了Oracle语法

select a.user_id 
from table1 a
left outer join table2 b on a.user_id = b.user_id 
where b.sub_id = (select min(c.sub_id) 
                from table2 c 
                where b.user_id = c.user_id)
几点要点:

您需要有明确的业务规则。如果查询返回多行,那么您需要考虑为什么不仅仅是一个1:many关系-为什么是1:many关系?。您应该提出业务解决方案,而不仅仅是使用min,因为它给您一行。业务解决方案可能只是采取第一个方案,在这种情况下,min可能是答案,但您需要确保这是一个有意识的决定。 您应该尝试使用ANSI语法进行连接。不仅仅是因为它是标准的,而是因为你的语法并没有真正做到你认为它在做的事情,它不是一个外部连接,而且有些事情根本不可能用你的语法来做。 假设您最终使用了MIN解决方案,这里有一个不使用子查询的可能解决方案。您应该使用各种其他解决方案对其进行测试,以确保它们在结果上是等效的,并查看哪种性能最好

SELECT
     a.user_id, b.*
FROM
     dbo.Table_1 a
LEFT OUTER JOIN dbo.Table_2 b ON b.user_id = a.user_id AND b.sub_id = a.sub_id
LEFT OUTER JOIN dbo.Table_2 c ON c.user_id = a.user_id AND c.sub_id < b.sub_id
WHERE
     c.user_id IS NULL

您需要对其进行测试,看看它是否真的满足了您的需求,您可能需要对其进行调整,但基本思想是使用第二个左外部联接,以确保不存在子元素id低于第一个左外部联接中找到的子元素id的行(如果有)。您可以根据最终的业务规则调整第二个左外部联接中的条件。

好的,您已经有了一个有效的查询。如果你关心你能达到的速度

在表2中添加一个字段,该字段 标识哪个sub_id是 “第一个”或

在表1或其他表中跟踪表2的主键


我无法将整个查询转换为聚合查询。也许你应该发布你的实际查询,这样人们可以给你有用的答案。根据你发布的内容,这是一个很好的答案。如前所述,该查询不起作用。从表2中选择minc.sub_id,其中b.sub_id=c.sub_id将始终返回b.sub_id,使外部where子句:a.user_id=b.user_id和a.sub_id=b.sub_id这:其中a.user_id=b.user_id用于表示a.user_id*=b.user_id,查询被终止。它总是会返回b.sub_id。我认为詹姆斯是对的,除非你试图做一些不同的事情……是的,当有人编辑你的问题并改变其含义时,这有点糟糕。现在,看,这就是我想要的。谢谢至于业务规则,这里是业务:数据库和模式已经有8年以上的历史了。我的新应用程序需要从一对多表中获取一行,而不是要更改模式和所有其他应用程序的应用程序。