业主信息查询优化说明
📋 需求背景
系统需要支持两种业主信息查询:
- 本地车主信息 - 通过
owner_id
关联ownerinfo
表
- 月票车主信息 - 通过
month_ticket_id
关联month_tick
表
🔧 修改内容
1. 数据库表结构
violations表
-- 原有字段
owner_id INT COMMENT '车主ID(关联ownerinfo表)'-- 新增字段
month_ticket_id INT COMMENT '月票ID(关联month_tick表)'
is_monthly_ticket TINYINT(1) DEFAULT 0 COMMENT '是否月票车'
ownerinfo表(本地车主)
id INT PRIMARY KEY
ownername VARCHAR(50) COMMENT '业主姓名'
ownerphone VARCHAR(20) COMMENT '业主电话'
building VARCHAR(10) COMMENT '楼栋号'
units VARCHAR(10) COMMENT '单元号'
roomnumber VARCHAR(10) COMMENT '房间号'
community VARCHAR(100) COMMENT '小区名称'
credit_score INT COMMENT '信用分数'
month_tick表(月票车主)
id INT PRIMARY KEY
user_name VARCHAR(50) COMMENT '用户姓名'
user_phone VARCHAR(20) COMMENT '用户手机号'
park_name VARCHAR(100) COMMENT '车场名称'
ticket_name VARCHAR(100) COMMENT '月票名称'
valid_status INT COMMENT '有效状态:1=有效,0=无效'
2. SQL查询优化
修改前(只查询本地车主)
SELECT v.*,o.ownername as ownerName,o.ownerphone as ownerPhone,CONCAT(o.building, '栋', o.units, '单元', o.roomnumber, '室') as ownerAddress
FROM violations v
LEFT JOIN ownerinfo o ON v.owner_id = o.id
修改后(同时查询两种车主)
SELECT v.*,-- 业主信息(优先本地车主,其次月票车主)COALESCE(o.ownername, mt.user_name) as ownerName,COALESCE(o.ownerphone, mt.user_phone) as ownerPhone,CASE WHEN o.id IS NOT NULL THEN CONCAT(o.building, '栋', o.units, '单元', o.roomnumber, '室')WHEN mt.id IS NOT NULL THEN CONCAT(mt.park_name, '停车场月票车主')ELSE NULL END as ownerAddress,-- 业主类型标识CASE WHEN o.id IS NOT NULL THEN 'local'WHEN mt.id IS NOT NULL THEN 'monthly'ELSE 'unknown'END as ownerType,-- 月票专属信息mt.ticket_name as monthTicketName,mt.park_name as parkName,mt.valid_status as monthTicketStatus,-- 信用分数(仅本地车主有)o.credit_score as creditScoreFROM violations v
LEFT JOIN ownerinfo o ON v.owner_id = o.id
LEFT JOIN month_tick mt ON v.month_ticket_id = mt.id
3. 返回数据结构
响应字段说明
{"id": 1,"plateNumber": "川A12345","violationType": "超时停车","status": "pending",// === 业主信息(统一字段)==="ownerName": "张三", // 业主姓名(本地车主或月票车主)"ownerPhone": "13800138000", // 业主电话"ownerAddress": "1栋2单元301室", // 地址信息// === 业主类型标识 ==="ownerType": "local", // local=本地车主, monthly=月票车主, unknown=未知// === 本地车主专属信息 ==="ownerId": 71, // 本地车主ID(仅本地车主有值)"creditScore": 85, // 信用分数(仅本地车主有值)"community": "万象上东", // 小区名称(仅本地车主有值)// === 月票车主专属信息 ==="monthTicketName": "普通月票", // 月票名称(仅月票车主有值)"parkName": "万象上东停车场", // 车场名称(仅月票车主有值)"monthTicketStatus": 1 // 月票状态:1=有效, 0=无效(仅月票车主有值)
}
4. 查询优先级规则
- 优先级顺序:本地车主 > 月票车主 > 无车主信息
- 字段合并逻辑:
ownerName
: 优先使用ownerinfo.ownername
,其次month_tick.user_name
ownerPhone
: 优先使用ownerinfo.ownerphone
,其次month_tick.user_phone
ownerAddress
: 本地车主显示详细地址,月票车主显示车场信息
5. 前端适配建议
显示业主信息
// 根据业主类型显示不同的信息
function displayOwnerInfo(record) {const { ownerType, ownerName, ownerPhone, ownerAddress } = record;switch(ownerType) {case 'local':return `${ownerName} | ${ownerPhone} | ${ownerAddress}`;case 'monthly':return `${ownerName} | ${ownerPhone} | ${record.parkName}月票车主`;default:return '未知车主';}
}
显示业主标识
// 业主类型标签
function getOwnerTypeTag(ownerType) {const tags = {'local': { text: '本地车主', color: 'blue' },'monthly': { text: '月票车主', color: 'green' },'unknown': { text: '未知车主', color: 'gray' }};return tags[ownerType] || tags.unknown;
}
6. 性能优化建议
- 索引优化
-- 为violations表添加索引
CREATE INDEX idx_violations_owner_id ON violations(owner_id);
CREATE INDEX idx_violations_month_ticket_id ON violations(month_ticket_id);-- 为month_tick表添加索引
CREATE INDEX idx_month_tick_car_no ON month_tick(car_no);
CREATE INDEX idx_month_tick_park_name ON month_tick(park_name);
- 查询优化
- 使用
LEFT JOIN
而非INNER JOIN
,避免遗漏无车主信息的违规记录
- 使用
- 使用
COALESCE
函数合并字段,减少前端处理逻辑
- 使用
- 使用
CASE WHEN
明确标识业主类型
- 使用
7. 测试用例
测试数据
-- 本地车主违规记录
INSERT INTO violations (plate_number, owner_id, month_ticket_id, violation_type)
VALUES ('川A12345', 71, NULL, '超时停车');-- 月票车主违规记录
INSERT INTO violations (plate_number, owner_id, month_ticket_id, violation_type)
VALUES ('川A67890', NULL, 2, '未按位停车');-- 无车主信息违规记录
INSERT INTO violations (plate_number, owner_id, month_ticket_id, violation_type)
VALUES ('川A11111', NULL, NULL, '占用他人车位');
预期结果
- 本地车主:返回完整的业主信息和地址
- 月票车主:返回月票车主信息和车场名称
- 无车主信息:ownerType为'unknown',其他车主字段为空
✅ 优化效果
- 统一查询接口:一个SQL查询支持两种车主类型
- 完整业主信息:不遗漏任何类型的车主数据
- 清晰的类型标识:前端可根据ownerType区分处理
- 向后兼容:保持原有字段结构,新增扩展字段
- 高效查询:通过LEFT JOIN和索引优化查询性能
🔧 部署步骤
- 确认数据库表结构包含
month_ticket_id
字段
- 部署修改后的
ViolationsMapper.xml
- 部署修改后的
ViolationsServiceImpl.java
- 重启应用服务
- 测试验证查询结果
- 前端适配新的返回字段结构
⚠️ 注意事项
- 数据完整性:确保
month_tick
表数据完整且有效
- 权限控制:月票车主可能涉及不同的权限规则
- 性能监控:关注新增JOIN查询的性能表现
- 测试覆盖:充分测试两种车主类型的各种场景