4

我正在尝试在 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` 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)
4

4 回答 4

5

浪费了大量时间测试上述示例和其他随机来源,以了解如何更改 ... 中的标准分隔符","func.group_concat()然后按照直觉发现语法完全按照您的预期工作:传递您的分隔符作为论据。如:

from sqlalchemy import func
#write the query: db.session.query(...
...func.group_concat(Table.column_name, "; ")

因此,修改先前答案的示例:

DBSession.query(
   Posts, 
   func.group_concat(Post_Tags.tag_name, "/"))<...>

注意:这是 Python 3.5、SQLite 3、Flask-SQLAlchemy 2.3.2(安装了 SQLAlchemy 1.0.13)

于 2018-07-17T15:34:50.110 回答
4

实际上,您正确地执行了 group_concat 位:

DBSession.query(
   Posts, 
   func.group_concat(Post_Tags.tag_name.op('SEPARATOR')(literal_column('/'))))<...>

我不确定到底发生了什么,因为您的架构似乎无效,您的查询拼写错误的表名,并且根据错误判断,您试图将 python 代码输入 mysql。

对于像我一样在谷歌搜索时发现此页面的人,上面的代码位应该会有所帮助,而且显然还有来源:https ://groups.google.com/forum/#!msg/sqlalchemy/eNbOoRJ425s/bScfQVat15EJ

于 2014-01-20T12:55:03.150 回答
1

我终于得到了这个工作。

>>> str(func.group_concat(Keyword.text.op('separator')(text('","'))))
'group_concat(keywords.text separator ",")'
于 2014-09-26T05:36:32.423 回答
0

定义自定义函数元素似乎是处理该方法的最简单group_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)
于 2013-10-06T10:08:27.377 回答