从MySQL切换PostgreSQL后,改动的地方,注意事项!!!

1、大写字段加上双引号,写了脚本可以参考:mysql转pg脚本
2、IFNULL转换为COALESCE。
3、LIMIT分页两个参数一个page,limit转换为如下写法:

  // 计算 offset,这里假设 page 从 1 开始
    int offset = (page - 1) * limit;
    sql:limit #{limit} OFFSET #{offset}

4、如果是利用mybatisplus的提供的构造器,大写字段的话要加上双引号。代码如下:

QueryWrapper<RepBasicInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("\"ACCOUNT_ITEM_ID\"", accountId)
.select("\"ID\"",  "COALESCE(\"REVIEW\", '') AS \"REVIEW\"");

5、如果你的数据库字段是数字类型,代码中是string类型,需要进行转换。代码如下:

<if test="payment != '' and payment != null">
    AND "PAYMENT" = CAST(#{payment} AS numeric)  <!-- 假设 PAYMENT 应该是 numeric 类型 -->
</if>

6、MySQL中的YEAR()和MONTH()函数替换为了PostgreSQL的EXTRACT(YEAR FROM CURRENT_DATE)和EXTRACT(MONTH FROM CURRENT_DATE)。

YEAR()  --》EXTRACT(YEAR FROM CURRENT_DATE)
MONTH()  --》EXTRACT(MONTH FROM CURRENT_DATE)

7、DATE_FORMAT的替换,代码如下:

DATE_FORMAT(fu."CREATE_DT",'%m') 
转换为
to_char(fu."CREATE_DT", 'MM')
%Y => YYYY
%m => MM
%d => DD
%H => HH24
%i => MI
%s => SS

8、查询结果原本是数字类型,但我想要字符串怎么办,代码如下:

COALESCE(al."LAST_END_DEBIT" - al."LAST_END_CREDIT", '0')
转换为
COALESCE(NULLIF(al."INITIAL DEBIT", 0)::text,'')

待补充…

<think>好的,我需要帮助用户了解如何在PostgreSQL数据库中修改之前的SQL查询,以返回考核点对应的题目ID列表。首先,用户之前使用的是MySQL的GROUP_CONCAT函数,现在要切换PostgreSQL,所以需要对应的函数替换。 首先,我得确认PostgreSQL中是否有类似的聚合函数。记得PostgreSQL使用的是STRING_AGG函数,而不是GROUP_CONCAT。用户之前的修改建议中提到了这一点,所以需要替换为STRING_AGG。同时,需要确保语法正确,比如参数顺序和分隔符的指定。 接下来,原来的SQL中使用了DISTINCT来去重,PostgreSQL的STRING_AGG是否支持DISTINCT?是的,STRING_AGG可以和DISTINCT一起使用,但需要注意正确的语法位置,应该是STRING_AGG(DISTINCT column, separator)。所以需要调整原来的写法。 然后,用户可能还需要注意数据类型的问题,比如question_id是否是整数类型,换成字符串会不会有问题。不过通常在聚合时,数据库会自动处理类型换,但可能需要显式换,比如使用CAST或者::TEXT。 另外,用户可能关心返回的数据结构,比如questionIds是以逗号分隔的字符串,应用层需要拆分为列表。这部分需要提醒用户在应用层处理,比如使用split方法。 还需要检查GROUP BY子句是否正确,PostgreSQL对于GROUP BY的要求比较严格,所有非聚合字段必须包含在GROUP BY中。原来的查询已经按zqtp.test_point和ztp.title分组,应该是正确的,因为这两个字段是主键或唯一标识。 然后,考虑性能问题。如果数据量大,STRING_AGG可能会影响性能,需要建议用户测试数据量。另外,是否有索引优化,比如在question_id或test_point字段上建立索引。 还要注意PostgreSQL的版本,STRING_AGG在较新的版本中可用,比如9.0及以上,但用户需要确认自己的版本是否支持。如果不支持,可能需要使用array_agg和array_to_string的组合。 最后,可能需要提供一个完整的示例,展示修改后的SQL,并说明每个部分的作用,确保用户能够直接复制使用,并理解改动地方。</think>--- ### PostgreSQL适配说明 以下是针对 **PostgreSQL 数据库**的适配调整后的SQL及详细解释: --- ### 修改后的SQL(适配PostgreSQL) ```sql SELECT zqtp.test_point AS testPointId, CASE WHEN ztp.title IS NULL THEN '默认考点' ELSE ztp.title END AS testPointName, -- 聚合题目ID为逗号分隔的字符串(PostgreSQL使用STRING_AGG) STRING_AGG(DISTINCT CAST(zer.question_id AS TEXT), ',') AS questionIds, -- 关键修改点 COUNT(*) AS testPointTotalNum, SUM(CASE WHEN zera.result = 1 THEN 1 ELSE 0 END) AS testPointRightNum, SUM(CASE WHEN zera.result = 1 THEN zera.scores::INT ELSE 0 END) AS testPointRightScore, (SUM(CASE WHEN zera.result = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*))::DECIMAL(5,2) AS userTestPointRightRate FROM zsh_exam_record zer LEFT JOIN zsh_question_test_point zqtp ON zer.question_id = zqtp.question_id LEFT JOIN zsh_test_point ztp ON zqtp.test_point = ztp.id LEFT JOIN zsh_exam_record_approve_record zera ON zera.history_id = #{historyId} AND zera.question_id = zer.question_id WHERE zer.history_id = #{historyId} GROUP BY zqtp.test_point, ztp.title; ``` --- ### 关键调整点解析 1. **聚合函数替换** - PostgreSQL 使用 `STRING_AGG(字段, 分隔符)` 代替 MySQL 的 `GROUP_CONCAT`。 - 示例:`STRING_AGG(DISTINCT CAST(question_id AS TEXT), ',')` - `CAST(question_id AS TEXT)`:确保字段类型为文本(如原字段是整数需显式换)。 - `DISTINCT`:去重,避免同一题目ID重复出现。 - `','`:指定分隔符(可自定义为其他符号,如`';'`)。 2. **类型换语法** - PostgreSQL 使用 `::类型` 或 `CAST(字段 AS 类型)`: - 示例:`scores::INT` 等价于 `CAST(scores AS INT)`。 3. **浮点数精度控制** - 正确率计算需显式换为浮点类型,避免整数除法截断: ```sql (SUM(...) * 100.0 / COUNT(...))::DECIMAL(5,2) -- 保留两位小数 ``` --- ### 返回数据结构示例 | testpointid | testpointname | questionids | testpointtotalnum | testpointrightnum | ... | |-------------|---------------|-------------|-------------------|-------------------|-----| | 101 | 语法考点 | 2001,2002 | 2 | 1 | ... | | 102 | 默认考点 | 2003 | 1 | 1 | ... | --- ### PostgreSQL特性优化建议 1. **数组格式返回** 如果需要直接返回数组类型(而非字符串),使用 `ARRAY_AGG` + `ARRAY_TO_STRING`: ```sql ARRAY_TO_STRING(ARRAY_AGG(DISTINCT zer.question_id), ',') AS questionIds ``` - 优势:保留数组结构,便于后续处理。 2. **JSON格式支持** PostgreSQL 支持直接生成JSON数组(需9.4+版本): ```sql JSON_AGG(DISTINCT zer.question_id) AS questionIds -- 返回如 [2001, 2002] ``` 3. **索引优化** - 若 `zqtp.test_point` 或 `zer.question_id` 查询频繁,建议添加索引: ```sql CREATE INDEX idx_zqtp_test_point ON zsh_question_test_point(test_point); CREATE INDEX idx_zer_question_id ON zsh_exam_record(question_id); ``` --- ### 注意事项 1. **空值处理** - 如果 `zer.question_id` 可能为 `NULL`,需过滤空值避免干扰聚合: ```sql STRING_AGG(DISTINCT NULLIF(zer.question_id, '')::TEXT, ',') ``` 2. **性能调优** - 数据量较大时,`STRING_AGG` 可能较慢,建议分页查询或限制聚合范围。 3. **版本兼容性** - `STRING_AGG` 需要 PostgreSQL 9.0+,若版本过低,改用 `ARRAY_AGG` + `ARRAY_TO_STRING`。 --- ### 扩展场景:返回题目详情列表 若需同时返回题目详细信息(如标题、难度),可使用 **子查询** 或 **LATERAL JOIN**: ```sql SELECT testPointId, testPointName, -- 嵌套查询获取题目详情 (SELECT JSON_AGG(JSON_BUILD_OBJECT('id', q.id, 'title', q.title)) FROM zsh_question_bank q WHERE q.id = ANY(STRING_TO_ARRAY(questionIds, ',')::INT[]) ) AS questionDetails, testPointTotalNum, ... FROM ( -- 原查询作为子查询 SELECT zqtp.test_point AS testPointId, ...其他字段..., STRING_AGG(...) AS questionIds FROM ... ) AS subquery; ``` --- 通过以上调整,SQL可在PostgreSQL中高效返回考核点及其对应的题目ID列表,并支持灵活扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FirstTalent

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值