我正在尝试按照[先提取然后再收费;根据列NETWORKCD
是否为空,先提取然后收费。但是,即使未显示数字,我的row_number公式仍在计算Null,例如:
+--------+-------------+------------+-----------+-------------+
| Acctid | Transaction | PostDate | NetworkCd | PeriodCount |
+--------+-------------+------------+-----------+-------------+
| 12345 | Withdrawal | 10/4/2018 | FRGN | 1 |
| 12345 | Fee | 10/4/2018 | | |
| 12345 | Withdrawal | 10/11/2018 | FRGN | 3 |
| 12345 | Fee | 10/11/2018 | | |
| 12345 | Withdrawal | 10/22/2018 | FRGN | 5 |
| 12345 | Fee | 10/22/2018 | | |
+--------+-------------+------------+-----------+-------------+
我对PeriodCount
使用以下公式
(case when networkcd is not null
then row_number() over (partition by acctid order by postdate)
end) PeriodCount
我期望PeriodCount计数为[1,2,3]而不是[1,3,5],如下所示:
+--------+-------------+------------+-----------+-------------+
| Acctid | Transaction | PostDate | NetworkCd | PeriodCount |
+--------+-------------+------------+-----------+-------------+
| 12345 | Withdrawal | 10/4/2018 | FRGN | 1 |
| 12345 | Fee | 10/4/2018 | | |
| 12345 | Withdrawal | 10/11/2018 | FRGN | 2 |
| 12345 | Fee | 10/11/2018 | | |
| 12345 | Withdrawal | 10/22/2018 | FRGN | 3 |
| 12345 | Fee | 10/22/2018 | | |
+--------+-------------+------------+-----------+-------------+
我想念什么?
答案 0 :(得分:3)
它仍然在第一,第三和第五行显示一个值-因此遇到这些行中的每一行时的行计数都是正确的。它是整个结果集中的行号,而不是非空值中的行号。您的case表达式将决定是否显示该值,而不影响其查找方式。
您可以使用dense_rank()
来获得所需的结果;
with your_table (Acctid, Transaction, PostDate, NetworkCd) as (
select 12345, 'Withdrawal', to_date('10/4/2018', 'MM/DD/YYYY'), 'FRGN' from dual
union all select 12345, 'Fee', to_date('10/4/2018', 'MM/DD/YYYY'), null from dual
union all select 12345, 'Withdrawal', to_date('10/11/2018', 'MM/DD/YYYY'), 'FRGN' from dual
union all select 12345, 'Fee', to_date('10/11/2018', 'MM/DD/YYYY'), null from dual
union all select 12345, 'Withdrawal', to_date('10/22/2018', 'MM/DD/YYYY'), 'FRGN' from dual
union all select 12345, 'Fee', to_date('10/22/2018', 'MM/DD/YYYY'), null from dual
)
select Acctid, Transaction, PostDate, NetworkCd,
(case when networkcd is not null then dense_rank() over (partition by acctid order by postdate) end) as periodcount
from your_table;
ACCTID TRANSACTIO POSTDATE NETW PERIODCOUNT
---------- ---------- ---------- ---- -----------
12345 Withdrawal 2018-10-04 FRGN 1
12345 Fee 2018-10-04
12345 Withdrawal 2018-10-11 FRGN 2
12345 Fee 2018-10-11
12345 Withdrawal 2018-10-22 FRGN 3
12345 Fee 2018-10-22
...这样可以抑制生成值中的间隙。 From the docs:
DENSE_RANK
计算行的有序组中某一行的排名,并将排名返回为NUMBER
。等级是从1开始的连续整数。...
答案 1 :(得分:1)
Alex Poole 的答案有效,但依赖于您的空行与您要计算的非空行具有相同的 POSTDATE
的事实。如果您将日期更改为彼此不同,您会看到密集排名失败:
with your_table (Acctid, Transaction, PostDate, NetworkCd) as (
select 12345, 'Withdrawal', to_date('10/1/2018', 'MM/DD/YYYY'), 'FRGN'
union all select 12345, 'Fee', to_date('10/2/2018', 'MM/DD/YYYY'), null
union all select 12345, 'Withdrawal', to_date('10/3/2018', 'MM/DD/YYYY'), 'FRGN'
union all select 12345, 'Fee', to_date('10/4/2018', 'MM/DD/YYYY'), null
union all select 12345, 'Withdrawal', to_date('10/5/2018', 'MM/DD/YYYY'), 'FRGN'
union all select 12345, 'Fee', to_date('10/6/2018', 'MM/DD/YYYY'), null
)
select
Acctid,
Transaction,
PostDate,
NetworkCd,
case when networkcd is not null then dense_rank() over (partition by Acctid order by PostDate) end as PeriodCount,
dense_rank() over (partition by Acctid order by PostDate) as DenseRank
from your_table
order by Acctid, PostDate, Transaction
;
收益
acctid transaction postdate networkcd periodcount denserank
------ ----------- ---------- --------- ----------- ---------
12345 Withdrawal 2018-10-01 FRGN 1 1
12345 Fee 2018-10-02 2
12345 Withdrawal 2018-10-03 FRGN 3 3
12345 Fee 2018-10-04 4
12345 Withdrawal 2018-10-05 FRGN 5 5
12345 Fee 2018-10-06 6
(在右侧,显示了没有空条件的dense_rank 的结果)所以它适用于您的情况,但总体上并不可靠。
Kevin Siemons 的答案效果更好:它分别计算空行和非空行,您可以简单地隐藏您对空行所做的计数:
with your_table (Acctid, Transaction, PostDate, NetworkCd) as (
select 12345, 'Withdrawal', to_date('10/1/2018', 'MM/DD/YYYY'), 'FRGN'
union all select 12345, 'Fee', to_date('10/2/2018', 'MM/DD/YYYY'), null
union all select 12345, 'Withdrawal', to_date('10/3/2018', 'MM/DD/YYYY'), 'FRGN'
union all select 12345, 'Fee', to_date('10/4/2018', 'MM/DD/YYYY'), null
union all select 12345, 'Withdrawal', to_date('10/5/2018', 'MM/DD/YYYY'), 'FRGN'
union all select 12345, 'Fee', to_date('10/6/2018', 'MM/DD/YYYY'), null
)
select
Acctid,
Transaction,
PostDate,
NetworkCd,
case when networkcd is not null then row_number() over (partition by Acctid, NetworkCd is not null order by PostDate) end as PeriodCount,
row_number() over (partition by Acctid, NetworkCd is not null order by PostDate) as RowNumber
from your_table
order by Acctid, PostDate, Transaction
;
收益
acctid transaction postdate networkcd periodcount rownumber
------ ----------- ---------- --------- ----------- ---------
12345 Withdrawal 2018-10-01 FRGN 1 1
12345 Fee 2018-10-02 1
12345 Withdrawal 2018-10-03 FRGN 2 2
12345 Fee 2018-10-04 2
12345 Withdrawal 2018-10-05 FRGN 3 3
12345 Fee 2018-10-06 3
我建议——使用 case when networkcd is not null then row_number() over (partition by Acctid, NetworkCd is not null order by PostDate) end as PeriodCount
。
答案 2 :(得分:0)
ROW_NUMBER()
函数无法按预期工作,但您可以这样做:
select t.*,
(select count(*)
from table t1
where t1.acctid = t.acctid and t1.PostDate <= t.PostDate and
t1.networkcd is not null
) as PeriodCount
from table t;
答案 3 :(得分:0)
它看起来不是空值,而是空字符串。 SQL在代码中将以不同的方式对待。
尝试:
case when networkcd = '' then row_number()....
答案 4 :(得分:0)
尝试将 partition by acctid
更改为 partition by acctid, NetworkCd IS NOT NULL