草庐IT

Go:在 SQL 连接结果后删除重复行

coder 2024-07-05 原文

我正在为位置和事件(发生在这些位置)运行联合 SQL 查询。在结果中,位置数据自然会按行复制,因为存在一对多关系:一个位置包含多个事件。

清理成倍增加的位置数据的最佳方法是什么?

继续使用单个 SQL 操作,最有意义的是在循环查询结果(行)时执行检查。

但是我似乎无法访问位置对象来检查预先存在的位置 ID。

编辑: 这是 SQL 输出。如您所见,位置数据自然会出现多次,因为它是跨事件共享的。最终这将作为 JSON 发送出去,带有嵌套结构,一个用于位置,一个用于事件。

id  title           latlng                  id  title           locationid  
1   Fox Thea...     43.6640673,-79.4213863  1   Bob's Event     1
1   Fox Thea...     43.6640673,-79.4213863  2   Jill's Event    1
2   Wrigley ...     43.6640673,-79.4213863  3   Mary's Event    2
3   Blues Bar       43.6640673,-79.4213863  4   John's Event    3
1   Fox Thea...     43.6640673,-79.4213863  5   Monthly G...    1
1   Fox Thea...     43.6640673,-79.4213863  6   A Special...    1
1   Fox Thea...     43.6640673,-79.4213863  7   The Final...    1

JSON 输出。如您所见,位置数据成倍增加,形成更大的 JSON 文件。

   {
        "Locations": [
            {
                "ID": 1,
                "Title": "Fox Theatre",
                "Latlng": "43.6640673,-79.4213863",
            },
            {
                "ID": 1,
                "Title": "Fox Theatre",
                "Latlng": "43.6640673,-79.4213863",
            },
            {
                "ID": 2,
                "Title": "Wrigley Field",
                "Latlng": "43.6640673,-79.4213863",
            },
            {
                "ID": 3,
                "Title": "Blues Bar",
                "Latlng": "43.6640673,-79.4213863",
            },
            {
                "ID": 1,
                "Title": "Fox Theatre",
                "Latlng": "43.6640673,-79.4213863",
            },
            {
                "ID": 1,
                "Title": "Fox Theatre",
                "Latlng": "43.6640673,-79.4213863",
            },
            {
                "ID": 1,
                "Title": "Fox Theatre",
                "Latlng": "43.6640673,-79.4213863",
            }
        ],
        "Events": [
            {
                "ID": 1,
                "Title": "Bob's Event",
                "Location": 1
            },
            {
                "ID": 2,
                "Title": "Jill's Event",
                "Location": 1
            },
            {
                "ID": 3,
                "Title": "Mary's Event",
                "Location": 2
            },
            {
                "ID": 4,
                "Title": "John's Event",
                "Location": 3
            },
            {
                "ID": 5,
                "Title": "Monthly Gathering",
                "Location": 1
            },
            {
                "ID": 6,
                "Title": "A Special Event",
                "Location": 1
            },
            {
                "ID": 7,
                "Title": "The Final Contest",
                "Location": 1
            }
        ]

    }

结构:

// Event type
type Event struct {
    ID int `schema:"id"`
    Title string `schema:"title"`
    LocationID int `schema:"locationid"`
}

// Location type
type Location struct {
    ID int `schema:"id"`
    Title string `schema:"title"`
    Latlng string `schema:"latlng"`
}

// LocationsEvents type
type LocationsEvents struct {
    Locations []Location `schema:"locations"`
    Events []Event `schema:"events"`
}

运行查询并循环遍历行的函数:

func getLocationsEvents(db *sql.DB, start, count int) ([]Location, []Event, error) {

    var locations = []Location{}
    var events = []Event{}

    rows, err := db.Query("SELECT locations.id, locations.title, locations.latlng, events.id, events.title, events.locationid FROM locations LEFT JOIN events ON locations.id = events.locationid LIMIT ? OFFSET ?", count, start)
    if err != nil {
        return locations, events, err
    }
    defer rows.Close()

    for rows.Next() {
        var location Location
        var event Event

        err := rows.Scan(&location.ID, &location.Title, &location.Latlng, &event.ID, &event.Title, &event.LocationID);
        if err != nil {
                return locations, events, err
        }

    // Here I can print locations and see it getting longer with each loop iteration
    fmt.Println(locations)

    // How can I check if an ID exists in locations?
    // Ideally, if location.ID already exists in locations, then only append event, otherwise, append both the location and event

        locations = append(locations, location)
        events = append(events, event)
    }

    return locations, events, nil
}

路由器调用的函数:

func (a *App) getLocationsEventsJSON(w http.ResponseWriter, r *http.Request) {

count := 99
start := 0

    if count > 10 || count < 1 {
        count = 10
    }
    if start < 0 {
        start = 0
    }

    locations, events, err := getLocationsEvents(a.DB, start, count)
    if err != nil {
        respondWithError(w, http.StatusInternalServerError, err.Error())
        return
    }

    var locationsEvents LocationsEvents

    locationsEvents.Locations = locations
    locationsEvents.Events = events

    respondWithJSON(w, http.StatusOK, locationsEvents)
}

以 JSON 形式发送数据的函数(REST API 的一部分):

func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) {
    response, _ := json.Marshal(payload)

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(code)
    w.Write(response)
}

更新:

回到使用 SQL 查询执行此操作,有哪些可能性?使用 GROUP BY?这是一个示例 SQL:

SELECT locations.id, locations.title, locations.latlng, events.id, events.title, events.locationid 从地点 在 locations.id = events.locationid 上左加入事件 GROUP BY locations.id, events.id

结果集仍然包含重复的位置数据,但已很好地分组和排序。

然后是子查询的可能性: http://www.w3resource.com/sql/subqueries/understanding-sql-subqueries.php但现在我正在运行多个 SQL 查询,这是我想避免的事情。

实际上,我不认为我可以像我一样在使用单个连接查询时避免重复的位置数据。如果不复制位置数据,我还能如何接收连接数据的结果集?让 SQL 服务器根据需要向我发送预制的 JSON 数据(位置和事件分开)?根据我的理解,最好在收到结果后再做这项工作。

最佳答案

我认为您可以将请求分为两部分:位置(SELECT * FROM locations)和事件(SELECT * FROM events),然后将它们传递给 JSON 编码器。 这 2 个请求对于数据库来说将非常容易和快速地执行。接下来他们将更容易缓存中间结果。

but now I'm running multiple SQL queries, something I wanted to avoid.

请您澄清一下 - 为什么要避免多次查询?你想解决什么任务,有什么限制?有时一组简单的小查询比一个过于复杂的查询要好。

关于Go:在 SQL 连接结果后删除重复行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44874566/

有关Go:在 SQL 连接结果后删除重复行的更多相关文章

  1. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  2. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  3. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  4. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  5. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  6. ruby - 如何安全地删除文件? - 2

    在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?

  7. ruby-on-rails - 标准化文件名的字符串,删除重音和特殊字符 - 2

    我正在尝试找到一种方法来规范化字符串以将其作为文件名传递。到目前为止我有这个:my_string.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n,'').downcase.gsub(/[^a-z]/,'_')但第一个问题:-字符。我猜这个方法还有更多问题。我不控制名称,名称字符串可以有重音符、空格和特殊字符。我想删除所有这些,用相应的字母('é'=>'e')替换重音符号,并将其余的替换为'_'字符。名字是这样的:“Prélèvements-常规”“健康证”...我希望它们像一个没有空格/特殊字符的文件名:“prelevements_routin

  8. Hive SQL 五大经典面试题 - 2

    目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类

  9. sql - 查询忽略时间戳日期的时间范围 - 2

    我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

  10. ruby-on-rails - 为什么在 Rails 5.1.1 中删除了 session 存储初始化程序 - 2

    我去了这个website查看Rails5.0.0和Rails5.1.1之间的区别为什么5.1.1不再包含:config/initializers/session_store.rb?谢谢 最佳答案 这是删除它的提交:Setupdefaultsessionstoreinternally,nolongerthroughanapplicationinitializer总而言之,新应用没有该初始化器,session存储默认设置为cookie存储。即与在该初始值设定项的生成版本中指定的值相同。 关于

随机推荐