选择列中具有第一个值的最后一行(包括最后一行)的行



给定这样的结果集,按AccountId排序:

| AccountId | Foo | Bar | ... |
| 7981      | x   |  12 | ... |
| 7981      | y   |  23 | ... |
| 7981      | z   |   8 | ... |
| 7981      | q   | 142 | ... |
| 64734     | x   |  31 | ... |
| 64734     | q   |  12 | ... |

我想选择第一AccountId的所有,无论AccountId的实际值如何,也不管行数如何。 (换句话说,选择所有行,直到第一列中的值发生更改。

获取此结果集需要大量的联接和子句,因此使用group by之类的东西和限制来获取子查询中的第一个AccountId不是我正在寻找的解决方案类型。因为我将不得不复制大量代码。

我一直在试验... over (partition by AccountId)函数。但它们似乎都对partition by创建的分区内的值进行操作。

我设想的一个解决方案是一个函数,它将数字 1 分配给第一个分区中的所有行partition by AccountId,将数字 2 分配给第二个分区中的所有行,依此类推。然后我可以添加where group = 1.

如何在子查询中选择最小 AccountId,然后显示具有此 AccountId 的所有行?

代码如下所示:

SELECT * 
FROM accounts
WHERE AccountId IN (
SELECT MIN(AccountId)
FROM accounts
)

编辑: 既然你说这是一个很长的查询,那么你可以通过使用 EXISTS 而不是 IN 运算符来让它更快一点:

SELECT * 
FROM accounts accsMain
WHERE EXISTS(
SELECT MIN(AccountId)
FROM accounts accsSub
WHERE accsMain.AccountId = accsSub.AccountId
)

如果只想引用该表一次,则可以使用窗口函数:

select t.*
from (select t.*, min(accountid) over () as min_accountid
from t
) t
where min_accountid = accountid;

rank()

select t.*
from (select t.*, row_number() over (order by accountid) as seqnum
from t
) t
where seqnum = 1;

如果t是复杂的查询或视图,这将非常有用。

以下查询返回第一个 AccountId 以及该帐户的所有其他行数据。下面的查询比其他解决方案更优化。

更新:我使用了多个 CTE 来解决问题。在更新中,您的查询仅使用过一次。

with
[query_result]
as
(
select
AccountId   ,
Foo         ,
Bar
from
[Your_Table]
),
first_account
as
(
select
AccountId,
row_number() over(order by AccountId) as RowNum
from
[query_result]
)
select
r.AccountId ,
r.Foo       ,
r.Bar
from
[query_result]  as r
inner join
first_account   as fa
on
r.AccountId = fa.AccountId
where
fa.RowNum = 1;

我不确定我是否理解你的情况。 您可以使用分析功能。

select * from (   
select first_value(AccountId) over() my_first_AccountId, complex_query.*
from 
( select AccountId ,... from t1,t2..,tn order by t1.x,t2.y,t3.z>  ) complex_query
)
where my_first_AccountId = AccountId

工作示例

select * from (
select first_value(table_name) over() my_first_value, complex_query.*
from 
( select * from user_tab_cols order by table_name ) complex_query
)
where my_first_value = table_name

避免重复代码的一种方法是使用WITH子句

with complex_query AS
(
SELECT AccountId, foo, bar, ...
... complex stuff here
)
SELECT *
FROM complex_query 
WHERE 
AccountId = ( SELECT MIN(AccountId) FROM complex_query) 
;

如果您更喜欢分析函数,则可以在不指定分区部分的情况下使用它们,如下所示

SELECT  MIN(AccountId) OVER() AS minAccountId, AccountId ...

然后它们对整个结果集进行操作

最新更新