这是一个非常常见的需求,根据文章的“价格”、“品牌”、“星级”等附加字段来筛选文章。

核心思路是:直接操作 dede_addonxx 数据表,因为附加字段的数据都存储在对应的附加表里。
第一步:理解附加字段的数据结构
在开始写 SQL 之前,你必须先明白 DedeCMS 是如何存储附加字段的。
-
主表:
dede_archives- 存储文章的基本信息,如 ID、标题、发布时间、点击量等。
- 关键字段:
id(文章ID),typeid(栏目ID)。
-
附加表:
dede_addonxx(dede_addonarticle,dede_addonsoft等)
(图片来源网络,侵删)- 表名中的
xx对应你文章模型ID的后两位,默认的文章模型ID是 1,所以附加表是dede_addonarticle。 - 存储文章的附加信息,如价格、作者简介、产品参数等。
- 关键字段:
aid: 文章ID,这是与dede_archives表关联的核心字段。typeid: 栏目ID,与主表一致。- 你自己创建的所有附加字段,如
price,brand,level等。
- 表名中的
重要提示: 在写 SQL 之前,请务必登录你的网站后台,进入【核心】->【内容模型管理】,查看你当前调用的模型是哪个,并确认其对应的附加表名称,对于文章,通常是 dede_addonarticle。
第二步:编写 SQL 语句
SQL 查询的关键在于通过 JOIN (连接) 将 dede_archives 表和附加表关联起来,然后在 WHERE 子句中指定附加字段的筛选条件。
基础语法结构
SELECT a.*, t.*
FROM dede_archives AS a
LEFT JOIN dede_addonarticle AS t ON a.id = t.aid
WHERE
[你的附加字段条件]
[其他可选条件,如栏目ID等]
ORDER BY a.id DESC
LIMIT 0, 10
SELECT a.*, t.*: 选择主表和附加表的所有字段。a和t是我们给表起的别名,方便书写。FROM dede_archives AS a: 指定主表并起别名为a。LEFT JOIN dede_addonarticle AS t ON a.id = t.aid: 这是核心,通过LEFT JOIN连接附加表dede_addonarticle(别名为t),连接条件是主表的id等于附加表的aid。WHERE ...: 设置查询条件。ORDER BY a.id DESC: 按文章ID倒序排列,最新发布的在前。LIMIT 0, 10: 限制返回结果数量,从第0条开始,取10条。
第三步:常用附加字段条件示例
假设我们的附加表是 dede_addonarticle,并且有以下附加字段:
price(价格, 类型为float或decimal)brand(品牌, 类型为varchar)level(星级, 类型为int, 1-5)is_recommend(是否推荐, 类型为tinyint, 0或1)
示例 1:筛选某个特定值
需求: 查找品牌为 "Apple" 的所有文章。

SELECT a.*, t.* FROM dede_archives AS a LEFT JOIN dede_addonarticle AS t ON a.id = t.aid WHERE t.brand = 'Apple' ORDER BY a.id DESC
示例 2:筛选数值范围
需求: 查找价格在 1000 到 5000 之间的所有文章。
SELECT a.*, t.* FROM dede_archives AS a LEFT JOIN dede_addonarticle AS t ON a.id = t.aid WHERE t.price BETWEEN 1000 AND 5000 ORDER BY a.id DESC
或者使用 AND:
WHERE t.price >= 1000 AND t.price <= 5000
示例 3:筛选多个条件 (AND)
需求: 查找品牌为 "Sony" 并且 星级为 5 的文章。
SELECT a.*, t.* FROM dede_archives AS a LEFT JOIN dede_addonarticle AS t ON a.id = t.aid WHERE t.brand = 'Sony' AND t.level = 5 ORDER BY a.id DESC
示例 4:筛选多个条件 (OR)
需求: 查找品牌为 "Apple" 或者 品牌为 "Samsung" 的文章。
SELECT a.*, t.* FROM dede_archives AS a LEFT JOIN dede_addonarticle AS t ON a.id = t.aid WHERE t.brand = 'Apple' OR t.brand = 'Samsung' ORDER BY a.id DESC
示例 5:结合栏目ID进行筛选 (非常常用)
需求: 在栏目ID为 5 的栏目下,查找价格大于 2000 的文章。
SELECT a.*, t.* FROM dede_archives AS a LEFT JOIN dede_addonarticle AS t ON a.id = t.aid WHERE a.typeid = 5 AND t.price > 2000 ORDER BY a.id DESC
注意:这里我们在 WHERE 中同时使用了主表的条件 a.typeid = 5 和附加表的条件 t.price > 2000。
示例 6:筛选是否为空 (NULL)
需求: 查找 price 字段没有被填写的文章。
SELECT a.*, t.* FROM dede_archives AS a LEFT JOIN dede_addonarticle AS t ON a.id = t.aid WHERE t.price IS NULL ORDER BY a.id DESC
示例 7:筛选非空值
需求: 查找 price 字段已经被填写的文章。
SELECT a.*, t.* FROM dede_archives AS a LEFT JOIN dede_addonarticle AS t ON a.id = t.aid WHERE t.price IS NOT NULL ORDER BY a.id DESC
示例 8:使用 LIKE 进行模糊查询
需求: 查找品牌名称中包含 "华" 字的文章。
SELECT a.*, t.* FROM dede_archives AS a LEFT JOIN dede_addonarticle AS t ON a.id = t.aid WHERE t.brand LIKE '%华%' ORDER BY a.id DESC
是通配符,代表任意数量的任意字符。
第四步:在 DedeCMS 中使用 SQL
写好 SQL 语句后,你可以在 DedeCMS 的两个主要地方使用它:
在 {dede:sql} 标签中直接调用
这是最直接的方式,适用于在模板页的任意位置执行一次性的 SQL 查询。
语法:
{dede:sql sql='你的完整SQL语句'}
<li>
<a href='[field:id runphp='yes'] $row['arcurl']; [/field:id]'>[field:title/]</a>
<p>价格: [field:price/]</p>
</li>
{/dede:sql}
重要提示:
- 在
{dede:sql}中,SQL 查询返回的每一行数据都会被循环处理。 - 字段的调用方式是
[field:你的附加字段名/]。 - 获取文章链接需要用到
arcurl,它需要通过runphp来获取,更简单的方法是直接查询dede_archives表中的arcurl字段。
优化后的示例:
{dede:sql sql="
SELECT a.id, a.title, a.arcurl, t.price
FROM dede_archives AS a
LEFT JOIN dede_addonarticle AS t ON a.id = t.aid
WHERE t.brand = 'Apple'
ORDER BY a.id DESC
LIMIT 0, 10
"}
<li>
<a href='[field:arcurl/]'>[field:title/]</a>
<p>价格: [field:price/]</p>
</li>
{/dede:sql}
在后台“自定义SQL查询”中执行
如果你只是想测试你的 SQL 语句或者获取数据,可以:
- 登录 DedeCMS 后台。
- 进入【系统】-> SQL命令行工具。
- 在文本框中粘贴你的完整 SQL 语句。
- 点击“查询”按钮,系统会返回查询结果,这非常适合调试。
总结与最佳实践
- 确认表名: 务必确认你的附加表是
dede_addonarticle,dede_addonsoft还是其他。 - 使用别名: 使用
AS a和AS t这样的别名能让 SQL 语句更清晰、更短。 - 关联字段: 记住关联永远是
a.id = t.aid。 - 类型安全: 进行数值比较时(如
price > 100),确保字段类型是数值型,进行字符串比较时(如brand = 'Apple'),确保用单引号括起来。 - 性能考虑: 如果附加表数据量非常大,为附加字段(如
price,brand)在数据库中建立索引可以大大提高查询速度。 - 安全第一: SQL 语句中的条件来自用户输入(如搜索框),务必进行过滤和转义,防止 SQL 注入攻击,在
{dede:sql}中直接写死条件是安全的。
