Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 2008 如何编写检查前一行的SQL查询?_Sql Server 2008 - Fatal编程技术网

Sql server 2008 如何编写检查前一行的SQL查询?

Sql server 2008 如何编写检查前一行的SQL查询?,sql-server-2008,Sql Server 2008,我在SQL server中有一个表(已排序),其中包含以下内容: stringname ========== stringA stringA stringB stringB stringA stringC stringC stringC stringA stringname previous_stringname count ========== =================== ===== stringA NULL 1 stringA stri

我在SQL server中有一个表(已排序),其中包含以下内容:

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
我想输出以下内容:

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
也就是说,对于原始表中的每个stringname以及该stringname的每个前一个条目,我希望输出它具有每个前一个字符串的次数(第一个条目为NULL)

我将如何为此编写SQL查询


我使用的是SQL Server 2008。

下面的内容可以解决问题,但作为回报,我希望您用谷歌搜索“递归”,看看谷歌建议搜索什么:)

澄清:递归是通过在temp表和CTE之间的行-1上连接到行来实现的。此方法依赖于有一个独立的
IDENTITY
列(在本例中为
ID
),并使用
ROWNUMBER()
来说明ID中可能存在的任何间隙。由于
ROW\u NUMBER()
不能用于
JOIN
中,我不得不求助于在
CTE
的递归部分使用子查询。即使你知道你有连续的ID,我还是建议对这种查询使用
ROW\u 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

@威尔,你为什么需要身份栏

数据

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

递归是不必要的;只需使用:

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;

我不确定您是否能够在SQL中轻松地做到这一点。最好是查询数据,让程序处理逻辑。查找ROW_NUMBER()和self joinROW_NUMBER不会有帮助,因为不能按顺序使用常量。表中需要另一个标识符,如
IDENTITY
列,以确保按所需顺序查询stringnames。什么意思是表“已排序”?你的意思是说有一个聚集索引没有显示给我们,而这些行是按聚集索引键顺序排列的吗?我以前从未见过这种技巧,这对我来说是个新技巧:)在这种情况下,那么就不需要标识列了。当然,无论使用一个或两个CTE来获得结果,这都会成为一种设计偏好。