我的表格中有以下数据。
| Id | FeeModeId |Name | Amount|
---------------------------------------------
| 1 | NULL | NULL | 20 |
| 2 | 1 | Quarter-1 | 5000 |
| 3 | NULL | NULL | 2000 |
| 4 | 2 | Quarter-2 | 8000 |
| 5 | NULL | NULL | 5000 |
| 6 | NULL | NULL | 2000 |
| 7 | 3 | Quarter-3 | 6000 |
| 8 | NULL | NULL | 4000 |
如何编写此类查询以获得低于输出...
| Id | FeeModeId |Name | Amount|
---------------------------------------------
| 1 | NULL | NULL | 20 |
| 2 | 1 | Quarter-1 | 5000 |
| 3 | 1 | Quarter-1 | 2000 |
| 4 | 2 | Quarter-2 | 8000 |
| 5 | 2 | Quarter-2 | 5000 |
| 6 | 2 | Quarter-2 | 2000 |
| 7 | 3 | Quarter-3 | 6000 |
| 8 | 3 | Quarter-3 | 4000 |
答案 0 :(得分:13)
由于您使用的是SQL Server 2012,因此这是一个使用它的版本。它可能比其他解决方案更快,但您必须在数据上进行测试。
当列中有值并保持sum() over()
值的当前值时, Id
会按1
添加null
执行排序。然后使用计算的运行总和将结果分区为first_value() over()
。由Id
为运行总和生成的每个“组”行排序的第一个值具有您想要的值。
select T.Id,
first_value(T.FeeModeId)
over(partition by T.NF
order by T.Id
rows between unbounded preceding and current row) as FeeModeId,
first_value(T.Name)
over(partition by T.NS
order by T.Id
rows between unbounded preceding and current row) as Name,
T.Amount
from (
select Id,
FeeModeId,
Name,
Amount,
sum(case when FeeModeId is null then 0 else 1 end)
over(order by Id) as NF,
sum(case when Name is null then 0 else 1 end)
over(order by Id) as NS
from YourTable
) as T
在SQL Server 2012之前可以运行的东西:
select T1.Id,
T3.FeeModeId,
T2.Name,
T1.Amount
from YourTable as T1
outer apply (select top(1) Name
from YourTable as T2
where T1.Id >= T2.Id and
T2.Name is not null
order by T2.Id desc) as T2
outer apply (select top(1) FeeModeId
from YourTable as T3
where T1.Id >= T3.Id and
T3.FeeModeId is not null
order by T3.Id desc) as T3
答案 1 :(得分:3)
请尝试:
select
a.ID,
ISNULL(a.FeeModeId, x.FeeModeId) FeeModeId,
ISNULL(a.Name, x.Name) Name,
a.Amount
from tbl a
outer apply
(select top 1 FeeModeId, Name
from tbl b
where b.ID<a.ID and
b.Amount is not null and
b.FeeModeId is not null and
a.FeeModeId is null order by ID desc)x
OR
select
ID,
ISNULL(FeeModeId, bFeeModeId) FeeModeId,
ISNULL(Name, bName) Name,
Amount
From(
select
a.ID , a.FeeModeId, a.Name, a.Amount,
b.ID bID, b.FeeModeId bFeeModeId, b.Name bName,
MAX(b.FeeModeId) over (partition by a.ID) mx
from tbl a left join tbl b on b.ID<a.ID
and b.FeeModeId is not null
)x
where bFeeModeId=mx or mx is null
答案 2 :(得分:2)
试试这个 -
SELECT Id,
CASE
WHEN Feemodeid IS NOT NULL THEN
Feemodeid
ELSE
(SELECT Feemodeid
FROM Table_Name t_2
WHERE t_2.Id = (SELECT MAX(Id)
FROM Table_Name t_3
WHERE t_3.Id < t_1.Id
AND Feemodeid IS NOT NULL))
END Feemodeid,
CASE
WHEN NAME IS NOT NULL THEN
NAME
ELSE
(SELECT NAME
FROM Table_Name t_2
WHERE t_2.Id = (SELECT MAX(Id)
FROM Table_Name t_3
WHERE t_3.Id < t_1.Id
AND NAME IS NOT NULL))
END NAME,
Amount
FROM Table_Name t_1
答案 3 :(得分:2)
SELECT
T.ID,
ISNULL(T.FeeModeId,
(SELECT TOP 1 FeeModeId
FROM TableName AS T1
WHERE ID < T.ID AND FeeModeId IS NOT NULL
ORDER BY ID DESC)) AS FeeModeId,
ISNULL(Name,
(SELECT TOP 1 Name
FROM TableName
WHERE ID < T.ID AND Name IS NOT NULL
ORDER BY ID DESC)) AS Name,
T.Amount
FROM
TableName AS T
答案 4 :(得分:1)
id name
1 toto
2 NULL
3 NULL
4 titi
5 NULL
6 NULL
7 tutu
8 NULL
9 NULL
SELECT
id_table
,name
FROM
(
SELECT
T_01.id AS 'id_table'
,max(T_02.id) AS 'id_name'
FROM
names AS T_01
cross join
(
SELECT
id
,name
FROM
names
WHERE
name IS NOT NULL
) AS T_02
WHERE
T_02.id <= T_01.id
GROUP BY
T_01.id
) AS tt02
left join names
ON names.id = tt02.id_name
id_table name
1 toto
2 toto
3 toto
4 titi
5 titi
6 titi
7 tutu
8 tutu
9 tutu