T-SQL: номер строки только для строк с заполненным полем - PullRequest
0 голосов
/ 14 марта 2019

У меня есть таблица с первичным ключом типа integer и двумя столбцами varchar, например:

id   name    remarks 
-------------------------
1    text1   
2    text2   anyRemarks
3    text3   
4    text4   anyRemarks
5    text5
6    text6
7    text7   anyRemarks

Заполнены только некоторые замечания.

Теперь я хотел вычислить номер строки, но только для строк, которые заполнили замечания. Мне нужны все строки в результате, но счетчик должен увеличиваться только при заполнении примечаний. Итак, желаемый результат таков:

id   name    remarks     counter
----------------------------------
1    text1               0
2    text2   anyRemarks  1
3    text3               0
4    text4   anyRemarks  2
5    text5               0
6    text6               0
7    text7   anyRemarks  3

Мой подход заключался в использовании row_number и делать выборку следующим образом:

SELECT 
    id, name, remarks, 
    ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS counter 
FROM 
    table

Но это заполняет счетчик для любой строки.

Нужно ли работать с дополнительным выбором?

Любые другие предложения?

(Движок - SQL Server 2017, поэтому можно использовать все текущие функции)

Ответы [ 4 ]

3 голосов
/ 14 марта 2019

Один из возможных подходов к получению результатов:

Введите:

CREATE TABLE #Table (
    id int,
    name varchar(10),    
    remarks varchar(50)
)
INSERT INTO #Table
    (id, name, remarks)
VALUES
    (1, 'text1', NULL),
    (2, 'text2', 'anyRemarks'),
    (3, 'text3', NULL),
    (4, 'text4', 'anyRemarks'),
    (5, 'text5', NULL),
    (6, 'text6', NULL),
    (7, 'text7', 'anyRemark')

Заявление:

SELECT 
    id,
    name,
    remarks,
    CASE
        WHEN remarks IS NULL THEN 0 
        ELSE ROW_NUMBER() OVER (PARTITION BY CASE WHEN remarks is NULL THEN 0 ELSE 1 END ORDER BY id)
    END AS [Rn]
FROM #Table
ORDER BY id

Выход:

id  name    remarks     Rn
1   text1   NULL        0
2   text2   anyRemarks  1
3   text3   NULL        0
4   text4   anyRemarks  2
5   text5   NULL        0
6   text6   NULL        0
7   text7   anyRemark   3
1 голос
/ 14 марта 2019

Вы можете использовать оконную функцию SUM, чтобы получить промежуточную сумму, а затем оператор CASE в SELECT, чтобы проверить, должна ли отображаться промежуточная сумма.

;with cte as
(
    select  *, SUM(case when remarks is null then 0 else 1 end) OVER (ORDER BY id)numRemarks 
    from #Table
)

select id, name, remarks, case when remarks is null then 0 else numRemarks end as counter 
from cte
1 голос
/ 14 марта 2019

По порядку идентификаторов:

SELECT 
  t.id, t.name, t.remarks, 
  case 
    when t.remarks is null then 0
    else (select count(*) from table where remarks is not null and id < t.id) + 1 
  end as counter 
FROM table t
ORDER BY t.id

или с UNION ALL:

select *, 0 as counter from [table] where remarks is null
union all
select *, row_number() OVER(ORDER BY (id)) from [table] where remarks is not null
order by id
0 голосов
/ 14 марта 2019

Другой простой вариант - использовать count с over предложением:

SELECT  Id, 
        Name, 
        Remarks, 
        CASE WHEN Remarks IS NULL THEN 0 
        ELSE COUNT(Remarks) OVER(ORDER BY Id) END As Rn
FROM #Table
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...