Как написать запрос SQL, который проверяет предыдущую строку? - PullRequest
1 голос
/ 04 октября 2011

У меня есть таблица (уже отсортированная) на сервере SQL со следующим:

stringname
==========
stringA
stringA
stringB
stringB
stringA
stringC
stringC
stringC
stringA

Я хотел бы вывести следующее:

stringname previous_stringname count
========== =================== =====
stringA    NULL                1
stringA    stringA             1
stringA    stringB             1
stringA    stringC             1
stringB    stringA             1
stringB    stringB             1
stringC    stringA             1
stringC    stringC             2

То есть для каждого имени строки в исходной таблице и для каждой предыдущей записи этого имени строки я хотел бы вывести его с числом раз, которое было у каждой предыдущей строки (с NULL для первой записи).

Как мне написать SQL-запрос для этого?

Я использую SQL Server 2008.

Ответы [ 3 ]

2 голосов
/ 04 октября 2011

рекурсия не нужна; просто используйте:

select b.stringname as stringname, a.stringname as previous_stringname
    into #tmp
    from (select stringname, row_number() over (order by id /* $/0 */) as row from testing) a
    right outer join (select stringname, row_number() over (order by id /* $/0 */) as row from testing) b
    on a.row = b.row - 1;
select *, count(*) as [count] from #tmp group by stringname, previous_stringname;
1 голос
/ 04 октября 2011

Следующее сделает свое дело, но в ответ на ответ я хочу, чтобы вы отправили Google «рекурсию» и посмотрите, что Google предлагает для поиска:)

Уточнение: рекурсия происходит путем объединения строки - 1 в строку между временной таблицей и CTE. Этот метод зависит от наличия независимого столбца IDENTITY (в данном случае ID) и использует ROWNUMBER() для учета любых возможных пробелов в идентификаторах. Поскольку ROW_NUMBER() нельзя использовать в JOIN, мне пришлось прибегнуть к использованию подзапроса в рекурсивной части CTE. Даже если вы знаете, что у вас есть непрерывные идентификаторы, я бы порекомендовал использовать ROW_NUMBER для этого типа запроса в любом случае, чтобы быть в безопасности, потому что пробелы могут испортить его.

CREATE TABLE #tmp (id INT IDENTITY(1,1),stringname NVARCHAR(MAX))

INSERT #tmp (stringname)

VALUES
('stringA')
,('stringA')
,('stringB')
,('stringB')
,('stringA')
,('stringC')
,('stringC')
,('stringC')
,('stringA')

;WITH StringNames
AS(
SELECT
    ROW_NUMBER() OVER (ORDER BY ID) AS Row  --Accounts for gaps in ID
    ,stringname 
    ,CAST(NULL AS NVARCHAR(MAX)) AS previous_stringname     
FROM #tmp
WHERE id = 1
UNION ALL
SELECT t.Row
    ,t.stringname
    ,s.stringname AS previous_stringname
    FROM (
            SELECT
            ROW_NUMBER() OVER (ORDER BY ID) AS Row --Accounts for gaps in ID 
            ,stringname
            FROM #tmp) AS t
JOIN StringNames AS s ON t.row - 1 = s.row
)

SELECT 
    DISTINCT
    stringname
    ,previous_stringname
    ,COUNT(*) AS count  
 FROM StringNames
 GROUP BY 
    stringname
    ,previous_stringname
ORDER BY stringname
0 голосов
/ 04 октября 2011

@ Уил, зачем вам столбец идентификаторов?

Данные

CREATE TABLE #table (stringname NVARCHAR(MAX))

INSERT  #table (stringname)
VALUES  ('stringA')
        ,('stringA')
        ,('stringB')
        ,('stringB')
        ,('stringA')
        ,('stringC')
        ,('stringC')
        ,('stringC')
        ,('stringA')

Запрос

;WITH [cteRowNumbers] AS (
    SELECT  ROW_NUMBER() OVER (ORDER BY $/0) AS [RowNumber],
            [stringname],
            CAST(NULL AS NVARCHAR(MAX)) AS [previous_stringname]
    FROM #table
)
,[cteStringNames] AS (
    SELECT  [RowNumber], 
            [stringname], 
            [previous_stringname]
    FROM (
        SELECT TOP 1 
                [RowNumber], 
                [stringname], 
                [previous_stringname]
        FROM [cteRowNumbers]
    ) t
    UNION ALL
    SELECT  t.[RowNumber],
            t.[stringname],
            s.[stringname] AS [previous_stringname]
    FROM [cteRowNumbers] AS t
    INNER JOIN [cteStringNames] AS s 
        ON t.[RowNumber] - 1 = s.[RowNumber]
)

SELECT  [stringname],
        [previous_stringname],
        COUNT(*) AS [count]
FROM [cteStringNames]
GROUP BY stringname, previous_stringname
ORDER BY stringname
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...