【问题标题】:How to properly group SQL results set?如何正确分组 SQL 结果集?
【发布时间】:2025-11-29 18:40:01
【问题描述】:

SQL 菜鸟,请多多包涵!!

我在数据库中存储一个 3 元组 (x,y, {signal1, signal2,..})。
我有一个数据库,其中包含表坐标 (x,y) 和另一个名为信号 (signal, coordinate_id, group) 的表,它存储各个信号值。同一坐标可以有多个信号。

组只是一个任意整数,它将信号表中的条目标记为属于同一集合(假设它们属于同一坐标)。这样任何具有相同 'coordinate_id' 和 'group' 的信号一起形成一个元组,如上所示。

例如,

坐标表 信号表 ----------------- ----------------- |编号 | x |是 | |编号 |信号 |坐标id |集团 | | 1 | 1 | 2 | | 1 | 45 | 1 | 1 | | 2 | 2 | 5 | | 2 | 95 | 1 | 1 | | 3 | 33 | 1 | 1 | | 4 | 65 | 1 | 2 | | 5 | 57 | 1 | 2 | | 6 | 63 | 2 | 1 |

这将产生元组 (1,2 {45,95,33})、(1,2,{65,57})、(2,5, {63}) 等等。

我想为每个坐标检索 {signal1, signal2,...} 的集合。属于一个集合的信号具有相同的坐标id和组,但我不一定知道组值。我只知道如果某个特定坐标id的组值相同,那么所有具有该组的人都形成一个集合。

我尝试查看 SQL GROUP BY,但我意识到它是用于聚合函数的。

有人可以指出如何在 SQL 中正确执行此操作或提供改进我的数据库结构的提示。

【问题讨论】:

    标签: sql android sqlite


    【解决方案1】:

    SQLite 支持类似于 MySQL 的 GROUP_CONCAT() 聚合函数。它在组中汇总一组值,并以逗号分隔将它们连接在一起。

    SELECT c.x, c.y, GROUP_CONCAT(s.signal) AS signal_list
    FROM Signals s
    JOIN Coordinates ON s.coordinate_id = c.id
    GROUP BY s.coordinate_id, s.group
    

    SQLite 还允许选择列表中的列与 group-by 子句中的列之间的不匹配,尽管 ANSI SQL 和大多数实现并不严格允许这样做。

    【讨论】:

    • 感谢您的回复。这意味着我仍然必须解析逗号分隔的结果集才能得到我想要的,对吧?我给出的示例有点简化,但信号不仅仅是一列。信号信息有两列。解析字符串会产生更多开销,我宁愿避免。
    【解决方案2】:

    我个人会将数据库写成 3 个表:

    x_y(x, y, id)  coords_groups(pos, group, id)  signals(group, signal)  
    with signals.group->coords_groups.id and coords_groups.pos->x_y.id
    

    当您试图表示一个 4 维数组时。

    然后,要从几个坐标 (X, Y) 中获取信号列表的 ArrayList,您可以使用它

    SELECT temp."group", signals.signal 
    FROM (
        SELECT cg."group", cg.id
        FROM x_y JOIN coords_groups AS cg ON x_y.id = cg.pos
        WHERE x_y.x=X AND x_y.y=Y ) 
    AS temp JOIN signals ON temp.id=signals."group"
    ORDER BY temp."group" ASC
    

    (X Y在最里面)

    在这种伪代码中:

    getSignalsGroups(X, Y)
        ArrayList<List<Signals>> a
        List<Signals> temp
        query=sqlLiteExecute(THE_SQL_SNIPPET, x, y)
    
        row=query.fetch()        //fetch the first row to set the groupCounter
        actualGroup=row.group
        temp.add(row.signal)
    
        for(row : query)         //foreach row add the signal to the list
            if(row.group!=actualGroup)     //or reset the list if is a new group
                a.add(actualGroup, temp)
                actualGroup=row.group; temp= new List
            temp.add(row.signal)
        return a
    

    【讨论】: