17

我的表中有以下数据。

   | 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  |
4

5 回答 5

20

由于您使用的是 SQL Server 2012 ...这是一个使用它的版本。它可能比其他解决方案更快,但您必须在数据上进行测试。

sum() over()将通过在列中有值时Id添加并保持值的当前值来进行运行总和。然后使用计算的运行总和将结果划分为. 由运行总和生成的每个“组”行排序的第一个值具有您想要的值。1nullfirst_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小提琴

在 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

SQL小提琴

于 2013-05-21T12:29:41.810 回答
6

请试试:

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

或者

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
于 2013-05-21T12:43:20.923 回答
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
于 2013-05-21T12:29:24.613 回答
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
于 2013-05-21T12:26:09.047 回答
2
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
于 2015-05-21T15:18:38.170 回答