質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

1回答

5903閲覧

SQLのIN演算子をgolangから使いたい場合

m0a

総合スコア708

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2017/07/01 15:14

編集2017/07/01 15:37

golangでmysqlを使ってコードを書いています。

go

1func XXXX(db sql.DB, n int, 2 modifiedBefore *time.Time, 3 tags []string, 4 url string, 5) ([]*ContentsWithAll, error) { 6 7 tagsSql := strings.Repeat("?, ", len(tags)-1) + ` ) ` 8 const sqlstr = `SELECT ` + 9// SELECT部は省略 10 `FROM ` + 11 `((((contents ` + 12 `LEFT JOIN contents_urls ON ((contents_urls.content_id = contents.id))) ` + 13 `LEFT JOIN urls ON ((urls.id = contents_urls.url_id))) ` + 14 `LEFT JOIN contents_tags ON ((contents_tags.content_id = contents.id))) ` + 15 `LEFT JOIN tags ON ((tags.id = contents_tags.tag_id))) ` + 16 `WHERE modified < ? ` + 17 `AND tags.name in (? ` + tagsSql + 18 `AND urls.url like ? ` + 19 `GROUP BY contents.id ` + 20 `Limit ? ` 21 22 urlSql := fmt.Sprintf("%%%s%%", url) 23 24 // syntax error: unexpected urlSql, expecting ) 25 q, err := db.Query(sqlstr, *modifiedBefore, tags..., urlSql, n) 26 27 if err != nil { 28 return nil, err 29 } 30 defer q.Close() 31 32 // load results 33 var res []*ContentsWithAll 34 for q.Next() { 35 cwa := ContentsWithAll{} 36 37 // scan 38 err = q.Scan(/*省略*/) 39 if err != nil { 40 return nil, err 41 } 42 43 res = append(res, &cwa) 44 } 45 46 return res, nil 47} 48

先ず IN演算子の構文を含める場合sqlstrの?の数が可変長になります。

実際 stackoverflowの情報をヒントにsqlstrの?の数をtagsのtag数に応じて増減させています。
その場合のdb.Queryのパラメータの渡し方を教えて下さい。
現状 *modifiedBefore, tags..., urlSql, n という渡し方ではsyntaxerrorとなってしまいます。
どう渡せばいいんでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

args変数([]interface)を作って渡す引数を全部固めて渡すことで解決しました

go

1args := []interface{}{*modifiedBefore} 2 for _, tag := range tags { 3 args = append(args, tag) 4 } 5 args = append(args, urlSql, n) 6 q, err := db.Query(sqlstr, args...) 7 // q, err := db.Query(sqlstr, *modifiedBefore, tags..., urlSql, n)

実際にはqueryBuilder(squirrel)を使うのが一番いいのかなとわかりました

go

1 modifiedBefore := time.Now() 2 tags := []string{"go", "rust", "typescript"} 3 url := "//" 4 n := 100 5 tagsStmt := sq.Expr("CONCAT(DISTINCT tags.name SEPARATOR ',')") 6 q := sq.Select("id", 7 "account_id", 8 "pairs", 9 "complete_rate", 10 "point", 11 "title", 12 "description", 13 "created", 14 "modified"). 15 Column("CONCAT(DISTINCT urls.url SEPARATOR ',') as urls"). 16 // Column("(DISTINCT tags.name SEPARATOR ',') as tags"). 17 Column(sq.Alias(tagsStmt, "tags")). 18 From("contents"). 19 LeftJoin("contents_urls ON contents_urls.content_id = contents.id"). 20 LeftJoin("contents_tags ON contents_tags.content_id = contents.id"). 21 LeftJoin("tags ON tags.id = contents_tags.tag_id"). 22 Where(sq.Lt{"modified": modifiedBefore}). 23 Where(sq.Eq{"tags.name": tags}). 24 Where("urls.url like ?", fmt.Sprint("%", url, "%")). 25 GroupBy("contents.id"). 26 Limit(uint64(n)) 27 28 fmt.Println(q.ToSql())

実行結果

SELECT id, account_id, pairs, complete_rate, point, title, description, created, modified, CONCAT(DISTINCT urls.url SEPARATOR ',') as urls, (CONCAT(DISTINCT tags.name SEPARATOR ',')) AS tags FROM contents LEFT JOIN contents_urls ON contents_urls.content_id = contents.id LEFT JOIN contents_tags ON contents_tags.content_id = contents.id LEFT JOIN tags ON tags.id = contents_tags.tag_id WHERE modified < ? AND tags.name IN (?,?,?) AND urls.url like ? GROUP BY contents.id LIMIT 100 [go rust typescript %//%] <nil>

プレースホルダと引数の調整を自動化しますし。

投稿2017/07/01 15:40

編集2017/07/03 03:20
m0a

総合スコア708

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問