MySQL:使用别名定义CONCAT的数据类型

问题描述 投票:0回答:1

这个问题是关于在调用CONCAT并将其存储为别名时定义容量/最大长度的可能性。

我有一个相当复杂的MySQL查询,它使用Common Table Expressions(CTE)来建模注释。它创建一个新变量path,该变量由评论的分数(投票数)和ID组成,并用逗号分隔,并使用CONCAT与其父路径连接起来。这允许按分数对线程内的注释进行排序。

A path看起来像000010,000005,000014,000008,表示ID为8的评论的得分为14,其父级(其本身没有父级)的ID为5,得分为10。具有path这种格式的所有注释都可以按照我的需要对它们进行排序。

最重要的是,最初path仅包含一个ID为ID的乐谱,在递归调用中,当我们探访孩子时,我们将继续串联成越来越长的路径。

但是,似乎最初对CONCAT的调用立即将所有后续串联的大小限制为15,这是最长的初始串联,因此它们仅在15个字符之后被剪切。使初始串联的长度大于15,将随后的串联限制为最长的初始串联(因此实际上不会串联任何东西)。

[目前,我已经解决了这个问题,首先在右边填充了很多零,然后在递归调用中将其删除。但是,这使用了正则表达式,即使很简单,我也担心它对性能不好。

可以通过初始调用CONCAT来定义所创建的别名变量的容量/最大长度是什么?

这是所进行的查询:

WITH RECURSIVE first_comments (id, content, parent_id, user_id, created, votes, path) AS (
        (
            SELECT r.id, r.content, r.parent_id, r.user_id, r.created, r.votes, CONCAT_WS(",", LPAD(r.votes,6,0), LPAD(r.id,6,0), LPAD(0,243,0)) as path
            FROM (
                SELECT c.id, c.content, c.parent_id, c.user_id, c.created, COUNT(DISTINCT v.id) AS votes
                FROM comments AS c
                LEFT JOIN comment_votes AS v ON c.id = v.comment_id
                WHERE c.post_id = ? AND c.parent_id IS NULL
                GROUP BY c.id
            ) as r
        )
UNION ALL
        (
            SELECT r.id, r.content, r.parent_id, r.user_id, r.created, r.votes, CONCAT_WS(",", REGEXP_REPLACE(fle.path, ",[0]+$", ""), LPAD(r.votes,6,0), LPAD(r.id,6,0)) as path
            FROM first_comments AS fle
                JOIN (
                    SELECT c.id, c.content, c.parent_id, c.user_id, c.created, COUNT(DISTINCT v.id) AS votes
                    FROM comments AS c
                    LEFT JOIN comment_votes AS v ON c.id = v.comment_id
                    WHERE c.post_id = ?
                    GROUP BY c.id
                ) AS r ON fle.id = r.parent_id
        )
    )
SELECT id, content, parent_id, user_id, path, created, votes FROM first_comments
ORDER BY pat

((受:Order comments by thread path and by number of total votes启发)

[最初,我用path创建CONCAT_WS(",", LPAD(r.votes,6,0), LPAD(r.id,6,0), LPAD(0,243,0)) as path,这将创建包含最上面的注释的分数和ID(无父级),并在右边填充243零的路径。所以例如000010,000005,0...0代表ID为5的最上面的评论。

然后递归(但仅在第一次递归调用时有效,因为此后模式从不匹配),我们使用正则表达式删除所有尾随零,包括最后一个逗号,并添加此注释的分数和ID:CONCAT_WS(",", REGEXP_REPLACE(fle.path, ",[0]+$", ""), LPAD(r.votes,6,0), LPAD(r.id,6,0)) as path

因此,最好在path的初始定义中添加一些内容,而不是这种解决方法。但是我不知道还有什么其他可能和更好的方法?

感谢您的任何帮助和想法!

//编辑:在GMB的帮助下,并进行了少量添加,问题已得到解决(并得以简化),请参阅我在可接受答案下的评论。

mysql sql string count recursive-query
1个回答
1
投票

如何将路径附加到JSON数组而不是字符串中?这无缝地克服了您遇到的问题,您仍然可以order by

所以:

WITH RECURSIVE first_comments (id, content, parent_id, user_id, created, votes, js_path) AS (
    SELECT 
        c.id, 
        c.content, 
        c.parent_id, 
        c.user_id, 
        c.created, 
        COUNT(DISTINCT v.id) AS votes,
        JSON_ARRAY(LPAD(COUNT(DISTINCT v.id), 6, 0), LPAD(c.id, 6, 0)) as js_path
    FROM comments AS c
    LEFT JOIN comment_votes AS v ON c.id = v.comment_id
    WHERE c.post_id = ? AND c.parent_id IS NULL
    GROUP BY c.id
    UNION ALL
    SELECT 
        r.id, 
        r.content, 
        r.parent_id, 
        r.user_id, 
        r.created, 
        r.votes, 
        JSON_ARRAY_APPEND(
            fle.js_path, 
            '$', LPAD(r.votes, 6, 0), 
            '$', LPAD(r.id, 6, 0)
        ) as js_path
    FROM first_comments AS fle
    JOIN (
        SELECT 
            c.id, 
            c.content, 
            c.parent_id, 
            c.user_id, 
            c.created, 
            COUNT(DISTINCT v.id) AS votes
        FROM comments AS c
        LEFT JOIN comment_votes AS v ON c.id = v.comment_id
        WHERE c.post_id = ?
        GROUP BY c.id
    ) AS r ON fle.id = r.parent_id
)
SELECT id, content, parent_id, user_id, js_path, created, votes 
FROM first_comments
ORDER BY js_path

请注意,我将查询简化如下:

  • 递归查询的锚点中不需要子查询

  • [union all不需要在两个查询之间加括号

© www.soinside.com 2019 - 2024. All rights reserved.