Python 如何在sqlalchemy中编写一个group_concat函数?
我正在尝试用SQLAlchemy重新编写此mysql查询: 模式:Python 如何在sqlalchemy中编写一个group_concat函数?,python,sqlalchemy,Python,Sqlalchemy,我正在尝试用SQLAlchemy重新编写此mysql查询: 模式: CREATE TABLE `posts` ( `post_id` INT UNSIGNED PRIMARY AUTO_INCREMENT, `post_name` VARCHAR(255) ) Engine=InnoDB; CREATE TABLE `post_tags` ( `tag_id` INT UNSIGNED PRIMARY AUTO_INCREMENT, `tag_name` VAR
CREATE TABLE `posts` (
`post_id` INT UNSIGNED PRIMARY AUTO_INCREMENT,
`post_name` VARCHAR(255)
) Engine=InnoDB;
CREATE TABLE `post_tags` (
`tag_id` INT UNSIGNED PRIMARY AUTO_INCREMENT,
`tag_name` VARCHAR(255)
) Engine=InnoDB;
CREATE TABLE `post_tags_map` (
`map_id` INT PRIMARY AUTO_INCREMENT,
`post_id` INT NOT NULL,
`tags_id` INT NOT NULL,
FOREIGN KEY `post_id` REFERENCES `posts` (`post_id`),
FOREIGN KEY `post_id` REFERENCES `post_tags` (`tag_id`)
) Engine=InnoDB;
查询:
SELECT
posts.*,
GROUP_CONCAT( post_tags.tag_name order by post_tags.tag_name ) AS tags
FROM posts
LEFT JOIN posts_tags_map
ON posts_tags_map.post_id = posts.post_id
LEFT JOIN post_tags
ON posts_tags_map.tags_id = posts_tags.tag_id
WHERE posts.post_id = 1
GROUP BY post_id
以下是我所拥有的,但我不断得到:
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 /))
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)
定义自定义函数元素似乎是处理
group\u concat
方法的最简单方法
from sqlalchemy.sql import expression
import sqlalchemy
from sqlalchemy.ext import compiler
class group_concat(expression.FunctionElement):
name = "group_concat"
@compiler.compiles(group_concat, 'mysql')
def _group_concat_mysql(element, compiler, **kw):
if len(element.clauses) == 2:
separator = compiler.process(element.clauses.clauses[1])
else:
separator = ','
return 'GROUP_CONCAT(%s SEPARATOR %s)'.format(
compiler.process(element.clauses.clauses[0]),
separator,
)
并使用类似这样的方式:
query = select([
table.c.some_column,
expression.label(
'grouped column',
group_concat(
table.c.some_oter_column,
' separator ',
),
),
]).group_by(table.c.some_column)
事实上,你做得有点对:
DBSession.query(
Posts,
func.group_concat(Post_Tags.tag_name.op('SEPARATOR')(literal_column('/'))))<...>
DBSession.query(
帖子,
函数组(Post_Tags.tag_name.op('SEPARATOR')(literal_column('/')))
我不确定到底发生了什么,因为您的模式似乎无效,您的查询拼错了表名,从错误判断,您试图将python代码输入mysql
对于那些像我一样在谷歌搜索时发现这个页面的人来说,上面的代码应该会很有帮助,还有一个很明显的来源:我终于找到了这个工作
>>> str(func.group_concat(Keyword.text.op('separator')(text('","'))))
'group_concat(keywords.text separator ",")'
测试上述示例和其他随机源以了解如何更改
函数组中的标准定界字符,“
”,浪费了大量时间。。。只有遵循直觉并发现语法完全按照您预期的方式工作:将定界字符作为参数传递。
例如:
因此,修改前面答案的示例:
DBSession.query(
Posts,
func.group_concat(Post_Tags.tag_name, "/"))<...>
DBSession.query(
帖子,
函数组(Post_Tags.tag_name,“/”)
注意:这适用于Python 3.5、SQLite 3、Flask SQLAlchemy 2.3.2(安装了SQLAlchemy 1.0.13)这不起作用。它会“编译”到GROUP_CONCAT(name,“;”)
,实际上会将“;”附加到每个记录,但保留默认值“,”分隔符literal_列
调用在这里似乎是必要的,它使用.op('separator')('/'))
DBSession.query(
Posts,
func.group_concat(Post_Tags.tag_name, "/"))<...>