0

0

如何在 PHP 中精准查询 MySQL 数据库中指定年份与周数的费用记录

心靈之曲

心靈之曲

发布时间:2026-02-23 13:07:01

|

731人浏览过

|

来源于php中文网

原创

如何在 PHP 中精准查询 MySQL 数据库中指定年份与周数的费用记录

本文讲解如何解决因多条同周号(如 w10)但跨年数据导致的查询歧义问题,通过联合 week 与 year 字段进行精确匹配,并提供安全、可维护的 PHP + PDO 实现方案。

本文讲解如何解决因多条同周号(如 w10)但跨年数据导致的查询歧义问题,通过联合 `week` 与 `year` 字段进行精确匹配,并提供安全、可维护的 php + pdo 实现方案。

在实际业务系统中,仅依赖 week 字段(如 'w10')进行数据库查询极易引发数据混淆——尤其当表中存在多个年份的相同周编号记录(例如 w10 同时出现在 2021 和 2022 年)。您当前的代码未限定年份,导致 $base_charge = $stmt->fetch(...) 随机返回第一条匹配记录(如 ID=1 的 2021 年数据),而后续关联查询 expense WHERE week = ? 却误传了 $base_charge['id'](本应是主键,但此处逻辑错用为周标识),进一步加剧数据错位。

根本解决方案:始终以 (week, year) 作为联合查询条件,杜绝歧义。 推荐以下两种生产就绪型实现方式:

✅ 方案一:服务端自动绑定当前年份(推荐用于“默认显示本周”场景)

// 获取当前年份(4位)和ISO周数(两位,自动补零)
$currentYear = (int)date('Y');
$currentWeek = (int)date('W'); // 注意:date('W') 返回纯数字(如 10),非 'w10'
$weekParam = 'w' . str_pad($currentWeek, 2, '0', STR_PAD_LEFT); // 转为 'w10'

if (isset($_GET['selectWeek'])) {
    // 从 URL 解析 week 字符串,如 'w46' → 提取数字 46
    if (preg_match('/^w(\d{1,2})$/i', $_GET['selectWeek'], $matches)) {
        $weekParam = $_GET['selectWeek'];
        $targetWeek = (int)$matches[1];
    } else {
        die('Invalid week format. Use e.g., ?selectWeek=w46');
    }
} else {
    $targetWeek = $currentWeek;
}

// ✅ 精确查询:同时匹配 week 字符串和 year 数值
$stmt = $pdo->prepare(
    'SELECT * FROM expense_base_charge 
     WHERE week = ? AND year = ? 
     ORDER BY created_at DESC 
     LIMIT 1'
);
$stmt->execute([$weekParam, $currentYear]);
$base_charge = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$base_charge) {
    $msg = "No expense base charge found for week {$weekParam} in year {$currentYear}.";
}

⚠️ 关键注意

  • date('W') 返回的是纯数字(如 10),而您的数据库 week 字段存储为 'w10',需手动拼接;若可修改表结构,强烈建议将 week 改为 TINYINT 类型并存数字,提升索引效率与可读性。
  • 添加 ORDER BY created_at DESC LIMIT 1 确保即使存在重复数据也稳定返回最新记录。
  • 使用 preg_match 安全解析 URL 参数,防止 SQL 注入或格式错误。

✅ 方案二:显式支持年份+周数双参数(推荐用于灵活筛选场景)

升级 URL 接口为 ?selectWeek=46&selectYear=2023,后端直接使用整型比较:

立即学习PHP免费学习笔记(深入)”;

// 安全获取并校验参数
$targetWeek = filter_input(INPUT_GET, 'selectWeek', FILTER_VALIDATE_INT, [
    'options' => ['min_range' => 1, 'max_range' => 53]
]) ?? (int)date('W');

$targetYear = filter_input(INPUT_GET, 'selectYear', FILTER_VALIDATE_INT, [
    'options' => ['min_range' => 2020, 'max_range' => 2030]
]) ?? (int)date('Y');

// ✅ 直接数值匹配(假设 week 字段已改为 INT 类型)
$stmt = $pdo->prepare(
    'SELECT * FROM expense_base_charge 
     WHERE week = ? AND year = ? 
     ORDER BY created_at DESC 
     LIMIT 1'
);
$stmt->execute([$targetWeek, $targetYear]);
$base_charge = $stmt->fetch(PDO::FETCH_ASSOC);

? 进阶建议

  • 在 expense_base_charge(week, year) 上创建复合索引:CREATE INDEX idx_week_year ON expense_base_charge(week, year);
  • 若必须保留 'wXX' 字符串格式,可添加生成列(MySQL 5.7+):
    ALTER TABLE expense_base_charge 
    ADD COLUMN week_num TINYINT AS (CAST(SUBSTR(week, 2) AS UNSIGNED)) STORED;
    CREATE INDEX idx_weeknum_year ON expense_base_charge(week_num, year);

最后,请修正关联查询逻辑:您原代码中 $stmt->execute([$base_charge['id']]) 尝试用主键 id 去匹配 expense.week 字段,这明显语义错误。正确做法应是:

// ✅ 关联 expense 表时,应使用相同的 week & year 条件
if ($base_charge) {
    $stmt = $pdo->prepare(
        'SELECT * FROM expense 
         WHERE week = ? AND year = ? 
         ORDER BY created_at DESC'
    );
    $stmt->execute([$base_charge['week'], $base_charge['year']]);
    $expense = $stmt->fetchAll(PDO::FETCH_ASSOC);
}

通过以上改造,系统将严格按“年+周”二维坐标定位数据,彻底消除跨年同周号导致的混乱,同时提升安全性、可维护性与查询性能。

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

1026

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

335

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

379

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1802

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

377

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

1374

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

585

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

437

2024.04.29

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

1030

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 2.3万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 836人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号