简体   繁体   English

如何使用T-SQL的Exists关键字?

[英]How do I use T-SQL's Exists keyword?

I have a query I want to run as a subquery that will return a set of FK's. 我有一个查询要作为子查询运行,该查询将返回一组FK。 With them I want to return only rows that has a matching key. 对于它们,我只想返回具有匹配键的行。

Subquery: 子查询:

SELECT ID 
FROM tblTenantTransCode 
WHERE
    tblTenantTransCode.CheckbookCode = 
      (SELECT ID FROM tblCheckbookCode WHERE Description = 'Rent Income')

That will return all the transaction codes that have a checkbook code that matches Rent Income 这将返回所有具有与租金收入匹配的支票簿代码的交易代码

Now I want to select All Transactions where their transactioncode matches an ID returned in the subquery. 现在,我要选择所有事务的事务代码与子查询中返回的ID匹配的所有事务。 I've gotten this far, but SQL Server complains of a syntax error. 到目前为止,我已经了解了,但是SQL Server抱怨语法错误。 How can I do this? 我怎样才能做到这一点?

Full Query: 完整查询:

SELECT * 
FROM tblTransaction
WHERE
    tblTransaction.TransactionCode IN 
      (SELECT ID FROM tblTenantTransCode 
       WHERE tblTenantTransCode.CheckbookCode = 
           (SELECT ID FROM tblCheckbookCode WHERE Description = 'Rent Income'))

Tables: 表格:

tblCheckbookCode  
   ID  
   Description  
   Other Info  

tblTenantTransCode  
   ID  
   CheckbookCode <-- fk we're looking for   
                     in the tblCheckbookCode.   
                     We're selecting only checkbook codes   
                     that have the Description 'Rent Income'  
   Other Info  

tblTransactions  
   ID  
   TransactionCode <-- fk to tenant transaction code.   
                       We're looking for an ID that is returned   
                       in the above query/join

To answer your question about using the EXISTS keyword, here is an example query that uses an EXISTS predicate, based on the query as currently given in your question. 为了回答有关使用EXISTS关键字的问题,下面是一个示例查询,该查询基于您问题中当前给出的查询,使用EXISTS谓词。

SELECT t.*
      FROM tblTransaction t
     WHERE EXISTS
           ( 
             SELECT 1
               FROM tblTenantTransCode ttc
               JOIN tblCheckbookCode cc
                 ON (cc.ID = ttc.CheckbookCode AND cc.Description='Rent Income')
              WHERE ttc.ID = t.TransactionCode
           )

Additional Details: 额外细节:

We all recognize that there are a variety of SQL statements that will return the result set that meets the specified requirements. 我们都知道,有各种各样的SQL语句将返回满足指定要求的结果集。 And there are likely going to be differences in the observed performance of those queries. 这些查询的观察性能可能会有所不同。 Performance is particularly dependent on the DBMS, the optimizer mode, the query plan, and the statistics (number of rows and data value distribution). 性能尤其取决于DBMS,优化器模式,查询计划和统计信息(行数和数据值分布)。

One advantage of the EXISTS is that it makes clear that we aren't interested returning any expressions from tables in the subquery. EXISTS优点之一在于,很明显,我们对从子查询表中返回任何表达式都不感兴趣。 It serves to logically separate the subquery from the outer query, in a way that a JOIN does not. 它用于以逻辑上的方式将子查询与外部查询分开,而JOIN则没有。

Another advantage of using EXISTS is that avoids returning duplicate rows that would be (might be) returned if we were to instead use a JOIN . 使用EXISTS另一个优点是避免了返回重复的行,如果我们改为使用JOIN ,这些行将(可能)返回。

An EXISTS predicate can be used to test for the existence of any related row in a child table, without requiring a join. EXISTS谓词可用于测试子表中是否存在任何相关行,而无需联接。 As an example, the following query returns a set of all orders that have at least one associated line_item: 例如,以下查询返回一组至少具有一个关联的line_item的所有订单:

SELECT o.*
      FROM order o
     WHERE EXISTS
           ( SELECT 1
               FROM line_item li
              WHERE li.order_id = o.id
           )

Note that the subquery doesn't need to find ALL matching line items, it only needs to find one row in order to satisfy the condition. 请注意,子查询不需要查找所有匹配的订单项,只需要查找一行即可满足条件。 (If we were to write this query as a JOIN , then we would return duplicate rows whenever an order had more than one line item.) (如果我们将此查询编写为JOIN ,则每当订单中有一个以上订单项时,我们都会返回重复的行。)

A NOT EXISTS predicate is also useful, for example, to return a set of orders that do not have any associated line_items. NOT EXISTS谓词也很有用,例如,返回没有任何关联的line_items的一组订单。

SELECT o.*
      FROM order o
     WHERE NOT EXISTS
           ( SELECT 1
               FROM line_item li
              WHERE li.order_id = o.id
           )

Of course, NOT EXISTS is just one alternative. 当然, NOT EXISTS只是一种选择。 An equivalent result set could be obtained using an OUTER join and an IS NULL test (assuming we have at least one expression available from the line_item table that is NOT NULL) 可以使用OUTER连接和IS NULL测试获得等效的结果集(假设我们从line_item表中至少有一个不是NOT NULL的表达式)

SELECT o.*
      FROM order o
      LEFT
      JOIN line_item li ON (li.order_id = o.id)
     WHERE li.id IS NULL

There seems to be a lot of discussion (relating to answers to the original question) about needing to use an IN predicate, or needing to use a JOIN . 关于需要使用IN谓词或需要使用JOIN似乎有很多讨论(与原始问题的答案有关)。

Those constructs are alternatives, but aren't necessary. 这些构造是替代的,但不是必需的。 The required result set can be returned by a query without using an IN and without using a JOIN . 查询可以返回所需的结果集,而无需使用INJOIN The result set can be returned with a query that uses an EXISTS predicate. 可以通过使用EXISTS谓词的查询返回结果集。 (Note that the title of the OP question did ask about how to use the EXISTS keyword.) (请注意,OP问题的标题确实询问了如何使用EXISTS关键字。)

Here is another alternative query (this is not my first choice), but the result set returned does satisfy the specified requirements: 这是另一个替代查询(这不是我的首选),但是返回的结果集确实满足指定的要求:

SELECT t.*
      FROM tblTransaction t
     WHERE EXISTS
           ( 
             SELECT 1
               FROM tblTenantTransCode ttc
              WHERE ttc.ID = t.TransactionCode
                AND EXISTS 
                    (
                      SELECT 1 
                        FROM tblCheckbookCode cc
                       WHERE cc.ID = ttc.CheckbookCode
                         AND cc.Description = 'Rent Income'
                    )
           )

Of primary importance, the query should return a correct result set, one that satisfies the specified requirements, given all possible sets of conditions. 最重要的是,查询应返回正确的结果集,该结果集应满足所有可能的条件集,并满足指定的要求。

Some of the queries presented as answers here do NOT return the requested result set, or if they do, they happen to do so by accident. 此处以答案形式出现的某些查询不会返回请求的结果集,或者如果返回的话,它们恰巧是偶然返回的。 Some of the queries will work if we pre-assume something about the data, such that some columns are UNIQUE and NOT NULL . 如果我们预先假设一些有关数据的查询,则某些查询将起作用,例如,某些UNIQUENOT NULL

Performance differences 性能差异

Sometimes a query with an EXISTS predicate will not perform as well as a query with a JOIN or an IN predicate. 有时,带有EXISTS谓词的查询的性能不如带有JOININ谓词的查询。 In some cases, it may perform better. 在某些情况下,它的性能可能更好。 (With the EXISTS predicate, the subquery only has to find one row that satisfies the condition, rather than finding ALL matching rows, as would be required by a JOIN .) (使用EXISTS谓词,子查询只需要查找满足条件的一行,而不必查找JOIN所需的所有匹配行。)

Performance of various query options is best gauged by observation. 各种查询选项的性能最好通过观察来衡量。

You are describing an inner join. 您正在描述内部联接。

select tc.id 
from tblTenantTransCode tc 
   inner join tblCheckbookCode cc on tc.CheckbookCode = cc.CheckbookCode

EDIT: It's still an inner join. 编辑:这仍然是一个内部联接。 I don't see any reason yet to use the IN clause. 我看不出有任何理由要使用IN子句。

select *
from tblTransaction t
   inner join tblTenantTransCode tc on tc.id = t.TransactionCode
   inner join tblCheckbookCode cc on cc.id = tc.CheckbookCode
where cc.description = 'Rent Income'

EDIT: If you must use the EXISTS predicate to solve this problem, see @spencer7953's answer. 编辑:如果必须使用EXISTS谓词来解决此问题,请参见@ spencer7953的答案。 However, from what I'm seeing, the solution above is simpler and there are assumptions of uniqueness based on the fact that "Subquery" works for you (it wouldn't 100% of the time if there wasn't uniqueness in that table). 但是,据我所知,上面的解决方案比较简单,并且基于“子查询”为您工作这一事实(因此如果该表中没有唯一性,则不会100%的时间),就存在唯一性假设)。 I'm also addressing 我也在讲

Now I want to select All Transactions where their transactioncode matches an ID returned in the subquery 现在,我要选择所有事务的事务代码与子查询中返回的ID 匹配的所有事务

in my answer. 在我的回答中。 If the request were something on the lines of this: 如果请求是这样的话:

Now I want to select All Transcations when any transactioncode matches an ID returned in the subquery. 现在, 当任何交易代码与子查询中返回的ID匹配时,我想选择“所有交易”。

I would use EXISTS to see if any transactioncode existed in the child table and return every row or none as appropriate. 我将使用EXISTS来查看子表中是否存在任何交易代码,并酌情返回每一行或不返回任何行。

Given your full query, this query will get you where you need to go using a single join. 给定您的完整查询,此查询将使您可以使用单个联接到达所需的位置。

The join filters out any transaction that doesn't have a transaction code of 'Rent Income.' 联接会过滤出没有“ Rent Income”交易代码的任何交易。 It will take all record from the first table, build out the subset of the second table (that WHERE clause limits the records), and then filters the first table where those table math the join condition. 它将从第一个表中获取所有记录,构建第二个表的子集(该WHERE子句限制了这些记录),然后过滤第一个表,其中那些表对联接条件进行数学运算。

SELECT 
    t.* 
FROM 
    tblTransaction t
    INNER JOIN tblTenantTransCode c ON
        t.TransactionCode = c.ID
    INNER JOIN tblCheckbookCode chk ON
        c.CheckbookCode = chk.ID
WHERE
    chk.Description = 'Rent Income'

Edit: One other note: Avoid using SELECT * -- always specify the columns. 编辑:另一个注意事项:避免使用SELECT *-始终指定列。 Edit Dos: I missed that there were three tables. 编辑注意事项:我错过了三张桌子。 Corrected! 更正! Thanks, spencer! 谢谢,斯潘塞!

Try this: 尝试这个:

SELECT
    tblTenantTransCode.ID 
    FROM tblCheckbookCode 
        INNER JOIN tblTenantTransCode ON tblCheckbookCode.ID=tblTenantTransCode.CheckbookCode
    WHERE tblCheckbookCode.Description = 'Rent Income'

Make sure you index tblCheckbookCode.Description . 确保您索引tblCheckbookCode.Description

You need to use the 'IN' clause: 您需要使用“ IN”子句:

select id from tblTenantTransCode
where tblTenantTransCode.CheckbookCode in
    (select id from tblCheckbookCode
     where description = 'rent income')

an inner join would probably be a better solution though... 内部连接可能是更好的解决方案...

select ttc.id from tblTenantTransCode as ttc
inner join tblCheckbookCode as tcc
    on ttc.CheckBookId = tcc.id
where tcc.description = 'rent income'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM