I am trying to re-write this mysql query in SQLAlchemy:
Schema:
JavaScript
x
18
18
1
CREATE TABLE `posts` (
2
`post_id` INT UNSIGNED PRIMARY AUTO_INCREMENT,
3
`post_name` VARCHAR(255)
4
) Engine=InnoDB;
5
6
CREATE TABLE `post_tags` (
7
`tag_id` INT UNSIGNED PRIMARY AUTO_INCREMENT,
8
`tag_name` VARCHAR(255)
9
) Engine=InnoDB;
10
11
CREATE TABLE `post_tags_map` (
12
`map_id` INT PRIMARY AUTO_INCREMENT,
13
`post_id` INT NOT NULL,
14
`tags_id` INT NOT NULL,
15
FOREIGN KEY `post_id` REFERENCES `posts` (`post_id`),
16
FOREIGN KEY `post_id` REFERENCES `post_tags` (`tag_id`)
17
) Engine=InnoDB;
18
Query:
JavaScript
1
13
13
1
SELECT
2
posts.*,
3
GROUP_CONCAT( post_tags.tag_name order by post_tags.tag_name ) AS tags
4
5
FROM posts
6
LEFT JOIN posts_tags_map
7
ON posts_tags_map.post_id = posts.post_id
8
LEFT JOIN post_tags
9
ON posts_tags_map.tags_id = posts_tags.tag_id
10
11
WHERE posts.post_id = 1
12
GROUP BY post_id
13
Here’s what I have, but I keep getting:
JavaScript
1
4
1
1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SEPARATOR /))
2
3
rows = DBSession.query(Posts,func.group_concat(Post_Tags.tag_name.op('SEPARATOR')(literal_column('/')))).outerjoin(PostsTagsMap,Posts.post_id==PostsTagsMap.post_id).outerjoin(Post_Tags,PostsTagsMap.tags_id==Post_Tags.tag_id).group_by(Posts.post_id)
4
Advertisement
Answer
Defining a custom function element seems the easiest way to take care of the group_concat
method.
JavaScript
1
21
21
1
from sqlalchemy.sql import expression
2
import sqlalchemy
3
from sqlalchemy.ext import compiler
4
5
6
class group_concat(expression.FunctionElement):
7
name = "group_concat"
8
9
10
@compiler.compiles(group_concat, 'mysql')
11
def _group_concat_mysql(element, compiler, **kw):
12
if len(element.clauses) == 2:
13
separator = compiler.process(element.clauses.clauses[1])
14
else:
15
separator = ','
16
17
return 'GROUP_CONCAT(%s SEPARATOR %s)'.format(
18
compiler.process(element.clauses.clauses[0]),
19
separator,
20
)
21
And use it something like this:
JavaScript
1
11
11
1
query = select([
2
table.c.some_column,
3
expression.label(
4
'grouped column',
5
group_concat(
6
table.c.some_oter_column,
7
' separator ',
8
),
9
),
10
]).group_by(table.c.some_column)
11