2

我有两张表:授权和结算。“结算”包含对授权的外键引用。

结算也可以有状态(错误、接受等)。

鉴于此数据:

授权结算
身份证号码 | 身份验证 ID | 地位
----- ---------------------------
1 1 1 错误
2 2 1 接受

我正在尝试编写一个 SQL 查询来查找所有没有 ACCEPTED 结算记录的授权。我尝试了 LEFT OUTER JOIN,但它返回的行太多。例如:

SELECT * FROM authorizations a
LEFT OUTER JOIN settlements s ON a.id = s.auth_id
WHERE s.status is null OR s.status != 'ACCEPTED'

这样做的问题是,如果它有多个结算记录,它仍然会返回一个授权记录,其中一个是 ACCEPTED。或者,如果有多个 ERROR 记录,授权将被返回两次。

如何仅获取没有相应结算记录且状态为“已接受”的单个授权记录?是否可以使用直接 SQL,或者我必须在我的代码中过滤结果?

4

3 回答 3

7
SELECT  *
FROM    authorizations a
WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    Settlements s
        WHERE   s.auth_id = a.id
                AND s.status = 'ACCEPTED'
        )
于 2009-08-10T17:28:15.250 回答
2

尝试

SELECT a.* FROM authorizations a
LEFT OUTER JOIN (SELECT S.* from settlements s1 
WHERE  s1.status = 'ACCEPTED')
ON a.id = s.auth_id
WHERE s.auth_id is null

这会挑选出所有被接受的记录,然后获取不在该组中的授权。

于 2009-08-10T17:43:47.637 回答
0

根据您的示例,如果您将 JOIN 更改为 RIGHT 连接,则无需检查 s.status 是否为空。

适用于 SQL Server 2005+ 或 Oracle 9i+:

WITH unacceptedSettlements AS (
     SELECT s.auth_id
       FROM SETTLEMENTS s
      WHERE s.status != 'ACCEPTED'
   GROUP BY s.auth_id)
SELECT t.*
  FROM AUTHORIZATIONS t
  JOIN unacceptedSettlements us ON us.auth_id = t.auth_id

任何数据库替代品:

SELECT t.*
  FROM AUTHORIZATIONS t
  JOIN (SELECT s.auth_id 
         FROM SETTLEMENTS s
         WHERE s.status != 'ACCEPTED'
      GROUP BY s.auth_id) us ON us.auth_id = t.auth_id  
于 2009-08-10T17:36:31.973 回答