我有两个类似的查询,它们都在同一个表上工作,我基本上想要将它们的结果组合起来,这样第二个查询就会为第一个查询不返回的内容提供默认值。我在这里尽可能地简化了这个问题。我正在使用Oracle btw。
该表中包含许多帐户的帐户信息,每个帐户都有多个条目,其中包含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 Merging two result sets - 我的情况显然比那更复杂
SQL to return a merged set of results - 我可能能够适应这种技术吗?我是一个被迫编写SQL的程序员,我不能很好地遵循这个例子,看看我如何根据我的需要修改它。
答案 0 :(得分:5)
执行此操作的标准方法是使用左外连接和合并。也就是说,您的整体查询将如下所示:
SELECT ...
FROM defaultQuery
LEFT OUTER JOIN currentQuery ON ...
如果您执行了SELECT *
,则每行将对应当前帐户数据加上您的默认值。和我一起到目前为止?
现在,对于要返回的每个列,不是SELECT *
,而是在匹配的列对上执行COALESCE()
:
SELECT COALESCE(currentQuery.columnA, defaultQuery.columnA) ...
这将选择当前帐户数据(如果存在),否则将选择默认数据。
答案 1 :(得分: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
子句使用您想要的逻辑选择适当的行。
答案 2 :(得分:1)
我结合了其他答案。在apex.oracle.com试了一下。这是一些解释。
MAX(CASE WHEN commit_date <= to_date('2010-DEC-30', 'YYYY-MON-DD'))
将在12月30日之前提供最新日期,如果没有,则为NULL。将其与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.*
。