SQL需要从列返回范围

SQL需要从列返回范围,sql,ms-access,range,gaps-and-islands,Sql,Ms Access,Range,Gaps And Islands,我有一个表,它有一个名为ID的整数列,其中的值可能有间隙,例如1,2,3,4,7,8,10,14,15,16,20 我想在上面的示例中找到一个查询,该查询将导致: 1-4 7-8 10 14-16 二十 =更新= 由于下面的代码在SQL Server中运行良好,我觉得我很快就能在MS Access中实现这一目标。我仍然得到一个语法错误,虽然在我的陈述,我不能找出 从中选择val 作为tbl 按PORTID ASC订购另一次尝试: SELECT MIN(i), MAX(i) FROM (

我有一个表,它有一个名为ID的整数列,其中的值可能有间隙,例如1,2,3,4,7,8,10,14,15,16,20

我想在上面的示例中找到一个查询,该查询将导致:

1-4 7-8 10 14-16 二十

=更新=

由于下面的代码在SQL Server中运行良好,我觉得我很快就能在MS Access中实现这一目标。我仍然得到一个语法错误,虽然在我的陈述,我不能找出

从中选择val

作为tbl 按PORTID ASC订购另一次尝试:

SELECT
    MIN(i), MAX(i)
FROM (
    select 
        i - (SELECT COUNT(*) FROM tbl t WHERE t.i < tbl.i) g,
        i 
    from tbl
) t
GROUP BY g
这肯定会很慢,但我看不到其他方法来对access中的行进行编号

SELECT val FROM
(
    -- Get the islands
    SELECT islands.ID, CAST(islands.ID as varchar(10)) as val 
    FROM @t1 islands
    WHERE NOT EXISTS (SELECT * FROM @t1 t2 WHERE t2.ID = islands.ID - 1)
    AND NOT EXISTS (SELECT * FROM @t1 t2 WHERE t2.ID = islands.ID + 1)

    UNION 
    
    -- Get the ranges
    SELECT 
        rngStart.ID
        ,CAST(rngStart.ID as varchar(10)) + '-' 
            + CAST(MIN(rngEnd.ID) as varchar(10)) as val
    FROM @t1 rngStart 
    INNER JOIN @t1 checkNext ON checkNext.ID = rngStart.ID + 1
    INNER JOIN
    (
        SELECT ID 
        FROM @t1 tblRangeEnd 
        WHERE NOT EXISTS (SELECT * FROM @t1 t2 WHERE t2.ID = tblRangeEnd.ID + 1)
    ) rngEnd on rngEnd.ID > rngStart.ID 
    WHERE NOT EXISTS (SELECT * FROM @t1 t2 WHERE t2.ID = rngStart.ID - 1)
    GROUP BY rngStart.ID
) as tbl
ORDER BY ID ASC
我使用了一个名为@t1的表变量,但只需将其替换为表名即可

它正在发挥作用

编辑 要在Access中工作,您必须稍微更改联接。试试这个:

SELECT val FROM
(
    SELECT islands.PORTID, CSTR(islands.PORTID) as val 
    FROM MYTABLE islands
    WHERE NOT EXISTS 
        (SELECT * FROM MYTABLE t2 WHERE t2.PORTID = islands.PORTID - 1)
    AND NOT EXISTS 
        (SELECT * FROM MYTABLE t2 WHERE t2.PORTID = islands.PORTID + 1)

    UNION 

    SELECT 
         rngStart.PORTID
        ,CSTR(rngStart.PORTID) + '-' + CSTR(MIN(endPORTID)) as val
    FROM MYTABLE rngStart 
    INNER JOIN 
    (
        SELECT checkNext.PORTID as nextPORTID, rngEnd.PORTID as endPORTID
        FROM MYTABLE checkNext
        INNER JOIN
        (
            SELECT rngEnd.PORTID
            FROM MYTABLE rngEnd 
            WHERE NOT EXISTS 
                (SELECT * FROM MYTABLE t2 WHERE t2.PORTID = rngEnd.PORTID + 1)
        ) AS rngEnd on rngEnd.PORTID > checkNext.PORTID - 1
    ) AS checkNext ON checkNext.nextPORTID = rngStart.PORTID + 1
    WHERE NOT EXISTS 
        (SELECT * FROM MYTABLE t2 WHERE t2.PORTID = rngStart.PORTID - 1)
    GROUP BY rngStart.PORTID
) as tbl
ORDER BY PORTID ASC

这将为您提供范围和范围之间的间距,以便您可以看到您拥有的或您需要的内容。提供的示例数据

如果您访问功能行编号,则此功能将起作用

或者使用子查询而不是公共表表达式

select min(ID) as MinID,
       max(ID) as MaxID
from (select ID,
             ID - row_number() over(order by ID) as grp
      from YourTable) as C
group by grp
结果:

MinID       MaxID
----------- -----------
1           4
7           8
10          10
14          16
20          20

在SQL Server上试用它

SQL Server?postgreSQL?神谕语法可能不同,因此了解正确的语法将非常有用。最终,我需要能够支持SQL Server、Oracle和Access。不幸的是,MS Access是最重要的。@user1069916:请参阅我的编辑,了解如何在Access中实现这一点。这一点的可能重复简直太棒了。非常感谢你。
with C as
(
  select ID,
         ID - row_number() over(order by ID) as grp
  from YourTable
)
select min(ID) as MinID,
       max(ID) as MaxID
from C
group by grp
select min(ID) as MinID,
       max(ID) as MaxID
from (select ID,
             ID - row_number() over(order by ID) as grp
      from YourTable) as C
group by grp
MinID       MaxID
----------- -----------
1           4
7           8
10          10
14          16
20          20