2017-07-02 7 views
0

場所とイベント(場所で発生する)の結合SQLクエリを実行しています。その結果、1対1の関係が存在するため、ロケーションデータは1行に当然複製されます.1つのロケーションには複数のイベントが格納されます。Go:SQL結合後に重複する行を削除する

乗算された位置データをクリーンアップする最適な方法は何ですか?

1つのSQL操作で、クエリ結果(行)をループしながらチェックを実行することが最も効果的です。

しかし、ロケーションオブジェクトにアクセスして、既存のロケーションIDを確認できないようです。

編集: これはSQL出力です。ご覧のように、ロケーションデータはイベント間で共有されるため、自然に複数回発生します。結局のところ、これはJSONとして最終的にはネストされた構造体で、場所用とイベント用に1つずつ送信されます。

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) 
} 

UPDATE:SQLクエリでこれを行うに戻す

、可能性は何ですか? GROUP BYを使用しますか?ここで例SQLは:

SELECT locations.id、locations.title、locations.latlng、events.id、events.titleは、 LEFTはlocations.id = events.locationid のイベントを登録しよう場所から をevents.locationid GROUP BY locations.id、events.id

結果セットには重複した場所データが含まれていますが、グループ分けして並べ替えて表示します。

サブクエリの可能性があります: http://www.w3resource.com/sql/subqueries/understanding-sql-subqueries.php今、私は避けたいと思っていた複数のSQLクエリを実行しています。

実際、私のように単一の結合クエリを使用すると重複した位置データを避けることはできません。場所データを複製せずに結合データの結果セットを受け取る方法は他にありますか?私はそれが必要な(場所とイベント別々に)事前に作られたJSONデータをSQLサーバに送ってもらうのですか?私の理解から、結果を受け取った後でその作業を行う方が良いです。

+0

予期した結果とともに現時点で取得したデータの例を提供します。あなたが提供したコードのクエリからは、あなたが観察している複製の種類は明白ではありません。元のデータに重複が含まれている場合にのみ、それらを取得する唯一の方法です。 – zerkms

+0

編集されたOPのSQL行出力。 – MarsAndBack

+0

私はそこに重複行が表示されません:すべての行は、あなたがちょうど投稿したものの値の一意の組み合わせです。 – zerkms

答えて

0

データベースを自分で照会する場合は、まず重複を避ける必要があります。 クエリの最後に「GROUP BY {ユニークフィールド}」を追加します。場所(SELECT * FROM locations)やイベント(SELECT * FROM events)、その後にそれらを渡す:あなたイベントリスト上にある場所のユニークなリストを与える必要があります

例は

SELECT location.* 
FROM location.ID, location.Title, location.Latlng 
    INNER JOIN event ON event.ID=location.ID 
GROUP BY location.ID 
+0

こんにちは私はこのアプローチを試みましたが、失敗しました。特定のフィールドでGROUP BYを使用すると、行が削除されます。 GROUP BYで複数のフィールドを使用すると、グループごとに行をソートするのに役立ちます。 OP編集を参照してください。 – MarsAndBack

+0

Aah、今回はあなたのテーブル構造を詳しく調べました。場所とイベントを多対多で接続しました。イベントは本当に複数の場所で開催できるのですか?それとも、多くのイベントで使用できる場所は同じですか? – Skov

+0

多くのイベントで使用できる同じ場所。 – MarsAndBack

1

私はあなたが二つにあなたの要求を分割することができると思いますJSONマーシャラー これらの2つの要求は、データベースが実行するのに非常に簡単で高速です。次に、中間結果をキャッシュするのが簡単になります。

今は複数のSQLクエリを実行していますが、避けたいものがあります。

この瞬間を明確にしてください - なぜ複数のクエリを避けたいですか?どのような課題を解決したいのですが、どのような制限がありますか?時には小さな簡単なクエリのセットは、複雑すぎるクエリよりも優れています。

関連する問題