SQL 需要从列返回范围

发布于 2024-12-18 05:40:29 字数 1097 浏览 2 评论 0原文

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

我想找到一个查询,在上面的示例中,结果如下:

1-4 7-8 10 14-16日 20

= UPDATE =

感谢下面的代码(似乎在 SQL Server 中运行良好),我觉得我非常接近让它在 MS-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(rngEnd.PORTID)) as val
FROM MYTABLE rngStart 
INNER JOIN MYTABLE checkNext ON checkNext.PORTID = rngStart.PORTID + 1
INNER JOIN
(
    SELECT PORTID 
    FROM MYTABLE tblRangeEnd 
    WHERE NOT EXISTS (SELECT * FROM MYTABLE t2 WHERE t2.PORTID = tblRangeEnd.PORTID + 1)
) rngEnd on rngEnd.PORTID > rngStart.PORTID 
WHERE NOT EXISTS (SELECT * FROM MYTABLE t2 WHERE t2.PORTID = rngStart.PORTID - 1)
GROUP BY rngStart.PORTID

) 作为表 按 PORTID ASC 订购

I have a table that has an integer column named ID with values that may have gaps (e.g. 1,2,3,4,7,8,10,14,15,16,20)

I would like to find a query that would, in the example above, result in this:

1-4
7-8
10
14-16
20

= UPDATE =

Thanks to the code below (which seems to work well in SQL Server), I feel I am very close to getting this to work in MS-Access which is the goal. I'm still getting a syntax error though in my statment which I can't figure out...

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(rngEnd.PORTID)) as val
FROM MYTABLE rngStart 
INNER JOIN MYTABLE checkNext ON checkNext.PORTID = rngStart.PORTID + 1
INNER JOIN
(
    SELECT PORTID 
    FROM MYTABLE tblRangeEnd 
    WHERE NOT EXISTS (SELECT * FROM MYTABLE t2 WHERE t2.PORTID = tblRangeEnd.PORTID + 1)
) rngEnd on rngEnd.PORTID > rngStart.PORTID 
WHERE NOT EXISTS (SELECT * FROM MYTABLE t2 WHERE t2.PORTID = rngStart.PORTID - 1)
GROUP BY rngStart.PORTID

) as tbl
ORDER BY PORTID ASC

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

雨后咖啡店 2024-12-25 05:40:29
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 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

I used a table variable called @t1 but just replace that with your table name.

Here it is in action.

EDIT

To make this work in Access you will have to change the joins a little bit. Try this:

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
記憶穿過時間隧道 2024-12-25 05:40:29
create table #sequence (id int not null primary KEY)

insert into #sequence(id)
    select 1
    union all select 2
    union all select 3
    union all select 4
    union all select 7
    union all select 8
    union all select 10
    union all select 14
    union all select 15
    union all select 16
    union all select 20


--Find Contig ranges
select l.id as start,
    (
        select min(a.id) as id
        from #sequence as a
            left outer join #sequence as b on a.id = b.id - 1
        where b.id is null
            and a.id >= l.id
    ) AS fend
from #sequence as l
    left outer join #sequence as r on r.id = l.id - 1
where r.id is null;

--Find missing values in sequence
select l.id + 1 as start, min(fr.id) - 1 as stop
from #sequence as l
    left outer join #sequence as r on l.id = r.id - 1
    left outer join #sequence as fr on l.id < fr.id
where r.id is null and fr.id is not null
group by l.id, r.id;

drop table #sequence

这将为您提供范围以及范围之间的差距,以便您可以看到您拥有什么或您需要什么。提供样本数据

create table #sequence (id int not null primary KEY)

insert into #sequence(id)
    select 1
    union all select 2
    union all select 3
    union all select 4
    union all select 7
    union all select 8
    union all select 10
    union all select 14
    union all select 15
    union all select 16
    union all select 20


--Find Contig ranges
select l.id as start,
    (
        select min(a.id) as id
        from #sequence as a
            left outer join #sequence as b on a.id = b.id - 1
        where b.id is null
            and a.id >= l.id
    ) AS fend
from #sequence as l
    left outer join #sequence as r on r.id = l.id - 1
where r.id is null;

--Find missing values in sequence
select l.id + 1 as start, min(fr.id) - 1 as stop
from #sequence as l
    left outer join #sequence as r on l.id = r.id - 1
    left outer join #sequence as fr on l.id < fr.id
where r.id is null and fr.id is not null
group by l.id, r.id;

drop table #sequence

This will give you both the ranges and the gaps between the ranges so you can see what you have or what you need. sample data provided

脸赞 2024-12-25 05:40:29

如果您访问函数 row_number(),这将起作用。

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

在 SQL Server 上尝试 https://data.stackexchange.com/stackoverflow/q/ 119411/

This will work if you access to function row_number().

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

or with a sub-query instead of a common table expression.

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

Result:

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

Try it on SQL Server https://data.stackexchange.com/stackoverflow/q/119411/

烂人 2024-12-25 05:40:29

另一种尝试:

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

它肯定会很慢,但我没有看到其他方法来对访问中的行进行编号。

Another try:

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

It'll be slow for sure, but I don't see other way to number rows in access.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文