3

我有 2 个类似的查询,它们都在同一个表上工作,我基本上想组合它们的结果,以便第二个查询为第一个查询不返回的内容提供默认值。我在这里尽可能地简化了问题。我正在使用 Oracle 顺便说一句。

该表中包含多个帐户的帐户信息,每个帐户有多个条目,并带有 commit_date 以告知何时插入帐户信息。我需要获取某个日期的最新帐户信息。

查询采用帐户 ID 列表和日期。

这是查询:

-- Select the row which was current for the accounts for the given date. (won't return anything for an account which didn't exist for the given date)
SELECT actr.*
FROM Account_Information actr 
WHERE actr.account_id in (30000316, 30000350, 30000351) 
AND actr.commit_date <= to_date( '2010-DEC-30','YYYY-MON-DD ')
AND actr.commit_date = 
(
    SELECT MAX(actrInner.commit_date) 
    FROM Account_Information actrInner 
    WHERE actrInner.account_id = actr.account_id
    AND actrInner.commit_date <= to_date( '2010-DEC-30','YYYY-MON-DD ')
) 

这看起来有点难看,但它为给定日期当前的每个帐户返回一行。问题是如果帐户在给定日期之后才存在,它不会返回任何内容。

为每个帐户选择最早的帐户信息很简单——我不需要为此提供日期:

-- Select the earliest row for the accounts.
SELECT actr.*
FROM Account_Information actr 
WHERE actr.account_id in (30000316, 30000350, 30000351) 
AND actr.commit_date = 
(
    SELECT MAX(actrInner .commit_date) 
    FROM Account_Information actrInner 
    WHERE actrInner .account_id = actr.account_id
)  

但我想以这样的方式合并结果集:

对于每个帐户,如果在第一个结果集中有它的帐户信息 - 使用它。否则,使用第二个结果集中的帐户信息。

我研究了所有我可以使用但没有成功的连接。联合几乎可以做到这一点,但它们只会合并唯一的行。我想根据每行中的帐户 ID 进行合并。

Sql合并两个结果集-我的情况显然比这更复杂

SQL 返回一组合并的结果- 我也许能够适应这种技术?我是一个被迫编写 SQL 的程序员,我不能很好地遵循这个例子,看我如何修改它以满足我的需要。

4

3 回答 3

5

执行此操作的标准方法是使用左外连接和合并。也就是说,您的整体查询将如下所示:

SELECT ...
FROM defaultQuery
LEFT OUTER JOIN currentQuery ON ...

如果你做了 a SELECT *,每一行将对应于当前帐户数据加上你的默认值。跟我到现在?

现在,SELECT *对于要返回的每一列,而不是 ,您COALESCE()对匹配的列对执行 a :

SELECT COALESCE(currentQuery.columnA, defaultQuery.columnA) ...

这将选择当前帐户数据(如果存在),否则将选择默认数据。

于 2013-03-06T03:49:47.263 回答
1

您可以使用分析函数更直接地执行此操作:

select *
from (SELECT actr.*, max(commit_date) over (partition by account_id) as maxCommitDate,
             max(case when commit_date <= to_date( '2010-DEC-30','YYYY-MON-DD ') then commit_date end) over
                   (partition by account_id) as MaxCommitDate2
      FROM Account_Information actr 
      WHERE actr.account_id in (30000316, 30000350, 30000351)
     ) t
where (MaxCommitDate2 is not null and Commit_date = MaxCommitDate2) or
      (MaxCommitDate2 is null and Commit_Date = MaxCommitDate) 

子查询计算两个值,即提交日期的两种可能性。然后该where子句使用您想要的逻辑选择适当的行。

于 2013-03-06T03:51:02.783 回答
1

我已经结合了其他答案。在apex.oracle.com上试用过。这里有一些解释。

MAX(CASE WHEN commit_date <= to_date('2010-DEC-30', 'YYYY-MON-DD'))将为我们提供不早于 12 月 30 日的最新日期,如果没有,则为 NULL。将它与 a 结合起来COALESCE,我们得到 COALESCE(MAX(CASE WHEN commit_date <= to_date('2010-DEC-30', 'YYYY-MON-DD') THEN commit_date END), MAX(commit_date)).

现在我们获取我们拥有的帐户 ID 和提交日期,并将它们与原始表连接起来以获取所有其他字段。这是我提出的整个查询:

SELECT *
FROM Account_Information
JOIN (SELECT account_id,
             COALESCE(MAX(CASE WHEN commit_date <=
                                    to_date('2010-DEC-30', 'YYYY-MON-DD')
                               THEN commit_date END),
                      MAX(commit_date)) AS commit_date
      FROM Account_Information
      WHERE account_id in (30000316, 30000350, 30000351)
      GROUP BY account_id)
  USING (account_id, commit_date);

请注意,如果您确实使用 USING,则必须使用*而不是acrt.*.

于 2013-03-06T05:22:08.637 回答