You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过SQL查询Moodle数据库中满足双自定义字段条件的课程记录

解决Moodle自定义字段多条件筛选的SQL问题

问题原因

你原来的SQL逻辑存在本质错误:每条mdl_customfield_data记录只对应一个自定义字段(要么是language,要么是institutions),不可能同时满足f.shortname = 'institutions'和f.shortname = 'language'两个条件,所以用AND会返回空结果;用OR则会把满足任意一个条件的课程全部列出,不符合「同时满足两个条件」的需求。

正确解法

方法1:多次关联自定义字段表

通过两次JOIN分别关联language和institutions的字段数据,直接筛选同时满足两个条件的课程:

SELECT c.*
FROM mdl_course c
-- 关联并筛选language=1的课程
JOIN mdl_customfield_data d_lang ON c.id = d_lang.instanceid
JOIN mdl_customfield_field f_lang ON f_lang.id = d_lang.fieldid 
    AND f_lang.shortname = 'language'
-- 关联并筛选institution包含2的课程
JOIN mdl_customfield_data d_inst ON c.id = d_inst.instanceid
JOIN mdl_customfield_field f_inst ON f_inst.id = d_inst.fieldid 
    AND f_inst.shortname = 'institutions'
WHERE d_lang.value = '1'
  AND (d_inst.value LIKE '%,2,%' 
       OR d_inst.value LIKE '2,%' 
       OR d_inst.value LIKE '%,2' 
       OR d_inst.value = '2')

方法2:子查询筛选课程ID

先分别找出满足单个条件的课程ID,再取交集得到同时满足两个条件的课程:

SELECT c.*
FROM mdl_course c
WHERE c.id IN (
    -- 获取language=1的课程ID
    SELECT instanceid
    FROM mdl_customfield_data d
    JOIN mdl_customfield_field f ON f.id = d.fieldid
    WHERE f.shortname = 'language' AND d.value = '1'
)
AND c.id IN (
    -- 获取institution包含2的课程ID
    SELECT instanceid
    FROM mdl_customfield_data d
    JOIN mdl_customfield_field f ON f.id = d.fieldid
    WHERE f.shortname = 'institutions'
      AND (d.value LIKE '%,2,%' 
           OR d.value LIKE '2,%' 
           OR d.value LIKE '%,2' 
           OR d.value = '2')
)

方法3:GROUP BY + HAVING聚合判断

先筛选出满足任意一个条件的记录,再通过分组确保课程同时拥有两个符合条件的字段记录:

SELECT c.*
FROM mdl_course c
JOIN mdl_customfield_data d ON c.id = d.instanceid
JOIN mdl_customfield_field f ON f.id = d.fieldid
WHERE (f.shortname = 'language' AND d.value = '1')
   OR (f.shortname = 'institutions' 
       AND (d.value LIKE '%,2,%' 
            OR d.value LIKE '2,%' 
            OR d.value LIKE '%,2' 
            OR d.value = '2'))
GROUP BY c.id
HAVING COUNT(DISTINCT f.shortname) = 2

优化小技巧

如果你的数据库是MySQL,可以用FIND_IN_SET函数简化institution的筛选条件,替代多个LIKE判断:

-- 替代原来的LIKE条件
FIND_IN_SET('2', d_inst.value) > 0

注意:FIND_IN_SET仅适用于逗号分隔的字符串,数据量较大时可能影响性能,这是Moodle现有结构下的折中方案。

内容的提问来源于stack exchange,提问作者J. Unkrass

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 23:47:24