空列值,但保持值等于使用SQL Query提供的数字

时间:2015-11-08 06:47:28

标签: sql sql-server

假设下表

ID         Name     RowNumber
2314       YY       1
213        XH       2
421        XD       3
123        AA       4
213        QQQ      5
12         WW       6
312        RR       7
123        GG       8
12         F        9
12         FF       10
312        VV       11
12         BB       12
32         NN       13
43         DD       14
53         DD       15
658        QQQQ     16
768        GGG      17

我想根据

条件用空字符串替换Name字段
  1. 不会删除第一个和最后一个单元格值。
  2. 需要返回不在连续单元格中的值。
  3. 只保留n个单元格
  4. 如果n小于或等于用户输入的数字而不是什么
  5. 例如,如果用户输入5,则只保留5个值,结果应为(或类似) -

    ID         Name     RowNumber
    2314       YY       1
    213                 2
    421                 3
    123        AA       4
    213                 5
    12                  6
    312                 7
    123        GG       8
    12                  9
    12                  10
    312                 11
    12                  12
    32         NN       13
    43                  14
    53                  15
    658                 16
    768        GGG      17
    

    可能会有更多的记录。

    我正在使用SQL Server

2 个答案:

答案 0 :(得分:1)

以下内容适用于SQL Server 2012+,因为它使用running / cumulative SUM。该查询假定RowNumber列中的值是从1行到总行数而没有间隙。如果您的数据不是这样,您可以使用ROW_NUMBER生成它们。

  • 计算给定数量N与总行数(CTE_Ratio)的比率
  • 计算此比率的运行总和,截断总和的小数部分(CTE_Groups
  • 正在运行的朗姆酒的每个整数值定义一组行,重新编号每组中的行数(CTE_Final
  • 仅为每个组的第一行保留Name

要更好地理解它的工作方式,将中间列(Ratio,GroupNumber,rn)包含在输出

SQL Fiddle

示例数据

DECLARE @T TABLE ([ID] int, [Name] varchar(50), [RowNumber] int);

INSERT INTO @T([ID], [Name], [RowNumber]) VALUES
(2314, 'YY', 1)
,(213, 'XH', 2)
,(421, 'XD', 3)
,(123, 'AA', 4)
,(213, 'QQQ', 5)
,(12, 'WW', 6)
,(312, 'RR', 7)
,(123, 'GG', 8)
,(12, 'F', 9)
,(12, 'FF', 10)
,(312, 'VV', 11)
,(12, 'BB', 12)
,(32, 'NN', 13)
,(43, 'DD', 14)
,(53, 'DD', 15)
,(658, 'QQQQ', 16)
,(768, 'GGG', 17);

DECLARE @N int = 5;

<强>查询

WITH
CTE_Ratio AS
(
    SELECT
        ID
        ,Name
        ,RowNumber
        ,COUNT(*) OVER() AS TotalRows
        ,CAST(@N-1 AS float) / CAST(COUNT(*) OVER() AS float) AS Ratio
    FROM @T
)
,CTE_Groups AS
(
    SELECT
        ID
        ,Name
        ,RowNumber
        ,TotalRows
        ,ROUND(SUM(Ratio) OVER(ORDER BY RowNumber), 0, 1) AS GroupNumber
    FROM CTE_Ratio
)
,CTE_Final AS
(
    SELECT
        ID
        ,Name
        ,RowNumber
        ,TotalRows
        ,ROW_NUMBER() OVER(PARTITION BY GroupNumber ORDER BY RowNumber) AS rn
    FROM CTE_Groups
)
SELECT
    ID
    ,CASE WHEN rn=1 OR RowNumber = TotalRows THEN Name ELSE '' END AS Name
    ,RowNumber
FROM CTE_Final
ORDER BY RowNumber;

<强>结果

+------+------+-----------+
|  ID  | Name | RowNumber |
+------+------+-----------+
| 2314 | YY   |         1 |
|  213 |      |         2 |
|  421 |      |         3 |
|  123 |      |         4 |
|  213 | QQQ  |         5 |
|   12 |      |         6 |
|  312 |      |         7 |
|  123 |      |         8 |
|   12 | F    |         9 |
|   12 |      |        10 |
|  312 |      |        11 |
|   12 |      |        12 |
|   32 | NN   |        13 |
|   43 |      |        14 |
|   53 |      |        15 |
|  658 |      |        16 |
|  768 | GGG  |        17 |
+------+------+-----------+

答案 1 :(得分:0)

试试这个:

--Number that user enter
DECLARE @InputNumber INT
DECLARE @WorkingNumber INT
DECLARE @TotalRecords INT
DECLARE @Devider INT
SET @InputNumber = 5
SET @WorkingNumber = @InputNumber -2
--Assume @InputNumber greater than 2 and @TotalRecords greater than 4
SELECT @TotalRecords = COUNT(*)
FROM Table;

SET @Devider = CONVERT(@TotalRecords, DECIMAL(18,2))/CONVERT(@WorkingNumber, DECIMAL(18,2));

WITH Conditioned (RowNumber)
AS
(
 SELECT RowNumber
 FROM Table
 WHERE RowNumber = 1
 UNION
 SELECT T.RowNumber
 FROM (SELECT TOP 1 RowNumber
       FROM Conditioned
       ORDER BY RowNumber DESC) AS C
      INNER JOIN Table AS T ON CONVERT(CEILING(C.RowNumber + @Devider), INT) = T.RowNumber
)
SELECT T.Id, CASE WHEN C.RowNumber IS NULL THEN '' ELSE T.Name END, T.RowNumber
FROM Table T
 LEFT OUTER JOIN Conditioned C ON T.RowNumber = C.RowNumber
WHERE
UNION RowNumber != @TotalRecords
SELECT Id, Name, RowNumber
FROM Table
WHERE RowNumber = @TotalRecords