news 2026/10/15 10:18:09

派出所综合信息管理系统设计:从数据建模到权限落地的工程实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
派出所综合信息管理系统设计:从数据建模到权限落地的工程实践

简介:派出所综合信息管理系统是“金盾工程”一期一类应用系统的重点建设内容,本方案面向公安信息化管理人员、系统集成商及基层派出所实务工作者,适用于派出所基础业务系统的整体规划与细化设计,能有效提升基层警务工作的科技含量与规范化水平。压缩包为单个doc文档,大小仅399KB,共1个文件,目录结构完整,内容紧凑便于传阅。目前已有441人学习下载。文档由专业信息工程公司编制,系统阐述了建设总体目标、设计原则、总体架构与功能模块,重点提出七大子系统、68个模块的划分思路,并对实战性、安全可靠性、经济实用性、可扩展性等原则进行深入剖析,同时给出信息模型、应用体系架构与基础业务功能设计说明。对于正在开展公安信息化项目设计或了解金盾工程应用系统的读者而言,这份资料可作为需求调研、方案编写及系统建设的重要参考。

1. 派出所综合信息管理系统:核心不是增删改查,而是底数清、情况明

某派出所把辖区人口台账从 Excel 挪进新系统后,第一周就发现两本账对不上:系统里常住人口比户籍部门给的数据少了一半。问题不在代码,而在初始数据迁移时地址格式不统一,同一个人拆成了两条记录。派出所综合信息管理系统,表面上是把接处警、人口、场所、案事件这些业务从纸质台账搬到线上,实质上要解决的是基层最头疼的“底数清、情况明”——数据准、更新快、权限不串。它的用户从所长到辅警都有,既有每天几十条接处警的高频操作,也有按月才碰一次的重点人员排查。这篇文章会从模块边界、技术选型、核心表结构、权限设计和常见坑五个层面,把这个系统讲透。

2. 功能域划分:接处警、人口、场所、案事件各自管到什么程度

派出所综合信息管理系统最常见的翻车方式,不是技术选型选错,而是需求范围没控制住。一个所里几十号人,涉及的条线很多,每个人都想把自己手头的活装进去,最后系统变成一个什么都装一点的大杂烩。所以做这个系统的第一步不是建表写接口,而是把功能域画清楚:哪些模块必须做,哪些模块只做台账不做流程,哪些事根本不该在这个系统里做。

2.1 接处警和案事件:高频业务与台账业务的边界

接处警是派出所每天使用频率最高的业务。110 指挥中心下发指令、值班民警接单、出警处置、现场反馈、事后回访,这是一条完整的闭环。在综合信息管理系统里,接处警模块至少要覆盖警情登记、派单、处置反馈、回访记录四件事,并且状态流转要能看出来进展:已登记、已派单、处置中、已反馈、已办结。这个模块的数据量看起来不大,一个所一年几千到几万条,但是字段复杂度高,同一个警情可能关联多个当事人、多个处置人,警情内容里还常常夹着地址、电话、经纬度这些半结构化信息。

案事件模块要克制。行政案件、刑事案件的全流程办理(受案、立案、调查、处罚、移送)通常在专门的执法办案系统里完成,派出所综合信息管理系统不需要再造一套流程。它只需要留案件台账:案件编号、案由、涉案人员、办案民警、当前阶段、文书状态,以及在接处警时自动生成的关联记录。这样日常浏览和统计有数据可依,又不碰专办系统的核心流程。常见做法是接处警模块和案件台账通过案件编号单向关联,不在这个系统里维护案件文书。

很多团队在这里犯了两个错误。一个是为案事件模块做了完整的审批流,结果跟专办系统打架,民警要录两遍;另一个是把案件表设计得过于简单,只有标题和状态,等要按案由、时限、涉案人统计时,发现字段根本不够。台账业务的正确姿势是:字段比流程多,状态比流程少,把关联查清楚比把审批走完更重要。

2.2 人口与场所管理:底数数据的采集和维护闭环

人口管理是这个系统的“底座”,因为接处警要关联当事人、重点人员管控要靠人口台账、案件统计要按辖区人口算发案率。人口台账的操作频率不如接处警,但对数据质量的要求极高。常见做法是把人口分成常住人口、流动人口、重点人员三类维护,其中重点人员要带标签和管控记录,比如吸毒人员、社区矫正对象、易肇事肇祸精神障碍患者——标签通常不建布尔字段,而是用标签表或 JSON 数组存,否则后期每加一类重点人员都要改表结构。

场所管理对应“地”和“物”的管控。辖区里哪些是治安重点场所、特种行业,多长时间检查一次,上次检查发现了什么问题,这些都要形成闭环:检查计划、检查记录、整改反馈。这一块往往是上线后被民警吐槽最多的地方,因为检查记录在纸质时代是能拖就拖的,到了系统里必须逐条录。所以场所检查表单要设计得尽量短,默认带上上次检查结论,民警到现场只需修改差异项。采集和维护闭环的意思是:数据不是一次录完就结束,要能通过日常业务自然更新,比如接处警中采集到的新地址能回流到人口地址字段,而不是让民警额外再录一遍。

2.3 角色权限与数据隔离:从所长到辅警分别能看什么

用户角色在这个系统里不是单纯的功能开关,而是数据范围问题。一个所里存在民警和辅警、社区民警和内勤、所领导和普通民警这些不同身份,他们对数据的可见范围和操作范围完全不一样。权限设计通常分三层:菜单权限控制能不能看到这个功能入口;数据权限控制能看到哪些单位的记录;字段权限控制敏感字段是否脱敏。实际项目中数据权限是最容易被低估的。很多系统上线时只做了菜单权限,结果辅警能打开案件详情,内勤能导出全部人员信息,一出事就是很大的问题。

我更建议在设计阶段就定死矩阵:所领导看全所数据,可以导出;值班民警处理本所警情,案件详情可见;社区民警默认只看自己的责任区数据;辅警看到的人员信息要做脱敏,手机号中间四位打星,且只有只读权限。这个矩阵定了,后续开发中的数据权限拦截器才有依据,否则每次加功能都要讨论谁能看谁不能看,开发效率极低。角色权限矩阵如下表所示:

角色数据范围敏感字段导出权限
所领导全所可看完整字段可导出
值班民警本所全部警情可看案件详情导出需审批
社区民警本所辖区按责任区过滤办案敏感字段脱敏不可导出
内勤全所台账数据人员手机号脱敏可导出
辅警本所人员信息脱敏显示不可导出

3. 技术选型与部署形态:数据量不大,但模型设计决定了未来半年改不改表

派出所综合信息管理系统的数据量级,放在互联网业务里根本不够看:一个区县几万到几十万人口,一个所一年几万条警情,单库单表完全够用。但这不意味着技术选型可以随便拍脑袋。真正影响后期开发效率的,是数据结构能不能跟上业务变化,以及部署形态合不合规。

3.1 数据库怎么选:PostgreSQL还是MySQL

我一般会优先选 PostgreSQL,理由不是它跑得快,而是它的类型系统更适合这种“字段老变”的业务。派出所系统的业务字段经常要加:今天加一个“是否安装反诈APP”,明天加一个“电动车防盗标签编号”,用 MySQL 就要频繁 ALTER TABLE,线上变更风险不小。PostgreSQL 的 JSONB 可以直接在人员表里存扩展标签,需要查询时建 GIN 索引也能撑住。虽然 MySQL 也有 JSON 类型,但在复杂查询和索引支持上,PG 的 JSONB 还是省心一些。

另一个选择是 MySQL 8.0,如果团队对 MySQL 更熟,也不是不行。核心思想是:主表只放高频查询和强约束字段,所有“可能变化”的属性都进字典或扩展字段。比如警情类型、案件阶段、人口标签,一律走字典表或 JSONB,不要建成形形色色的数字枚举列。这样以后加枚举值只加字典数据,不用动表结构。索引设计上,不要上来就给每张表建十几个索引。派出所系统的查询模式很固定:按单位过滤、按状态过滤、按时间范围过滤。所以核心表建组合索引就够了,最怕的是把查询条件做成任意组合,以为建了一堆单列索引就能覆盖所有情况,结果执行计划还是全表扫描。

3.2 后端与前端框架:政务环境的稳妥组合

后端框架我建议选 Spring Boot,主要原因不是技术多新,而是生态稳、会的人多、审计和安全组件齐全。政务类系统对代码审计、等保测评、日志留痕有硬要求,Spring Security 的过滤器链和注解体系能省很多事。如果团队更熟悉其他语言也不是不行,但安全和审计相关的轮子得自己补齐,成本会高不少。前端分成两个端:管理端用 Vue3 加 Element Plus,做表格、筛选、表单、弹窗这一套典型后端管理系统很顺畅;移动端用 H5 或 uni-app,跑在警务通浏览器的 WebView 里,重点是快速录入。

移动端不要直接拿 Web 端页面缩小了用,值班民警是单手拿警务通录警情,Web 端那一套多列表单在手机上根本没法操作。移动端的表单要做成“快录模式”,详情页是把 Web 端的字段有选择地展示,而不是全部堆上去。项目结构上做一个约定:Controller 只做参数校验和结果封装,业务逻辑在 Service 层完成,所有写操作必须带当前用户和单位信息。这样后续做数据权限、审计日志都只用在一处加代码,不用每个接口单独处理。

3.3 部署拓扑:公安信息网、移动端与数据交换区的关系

部署是这个系统里最需要提前对齐的事项。常见做法是系统主体部署在公安信息网上,也就是专网环境,互联网访问不了。移动端的警务通通过移动专网接入,不直接暴露公网端口。上级单位的数据交换走专门的数据交换区或者消息队列,不会让基层系统直接连上级库。这里有一个经常踩的坑:开发环境跑在互联网,生产环境在专网,依赖的地图服务、坐标系统在专网里可能根本没有,或者用的是另一套坐标。所以需求阶段就要确认清楚:警情经纬度用哪个坐标体系、移动端地图用哪家的离线服务、数据和上级平台交换的格式是 JSON 还是 XML。等部署到专网再发现地图坐标系不对,前端所有点位都偏,排查起来极其折腾。我一般建议在第一周就去找运维拿一份专网可用的服务清单,把地图、短信、文件存储、消息队列这些依赖项一次性列清楚,省得开发到一半发现底层能力不具备。

4. 手写核心表结构与接口:接处警、人口台账与数据权限过滤

这一章直接给可抄作业的部分。我以 PostgreSQL 为例,先写核心表 DDL,再写一个接处警登记接口,最后写数据权限的自动过滤思路。代码里的表名、字段名可以直接用,也可以按你们自己的命名规范调整,但业务含义别改。

4.1 警情表和人口表DDL:字段命名与索引设计的取舍

-- 警情主表:一次接警记录对应警情登记、派单和反馈的主表 CREATE TABLE t_alarm ( id BIGSERIAL PRIMARY KEY, alarm_no VARCHAR(32) NOT NULL UNIQUE, -- 警情编号,110指令号或系统生成 org_id BIGINT NOT NULL, -- 处理单位(派出所/警务站)ID,数据权限核心字段 alarm_type VARCHAR(16) NOT NULL, -- 警情类型,对应字典项,如 110/纠纷/求助 source_type VARCHAR(16) NOT NULL, -- 来源:110指令、群众报警、巡逻发现 level VARCHAR(8) DEFAULT 'normal', -- 紧急程度:normal/urgent content TEXT NOT NULL, -- 警情内容原文 address VARCHAR(256), -- 发生地址 lon NUMERIC(10, 6), -- 经度 lat NUMERIC(10, 6), -- 纬度 status VARCHAR(16) DEFAULT 'registered', -- 状态:registered/dispatched/dealing/finished receiver_id BIGINT, -- 接警人ID dispatcher_id BIGINT, -- 派单人ID deal_user_id BIGINT, -- 处置人ID deal_result TEXT, -- 处置反馈结果 finish_deadline TIMESTAMP, -- 要求反馈截止时间,用于按期反馈率计算 create_time TIMESTAMP DEFAULT now(), update_time TIMESTAMP DEFAULT now() ); -- 派出所/警务站组织表:用parent_id支持一个所管多个警务站 CREATE TABLE t_org ( id BIGSERIAL PRIMARY KEY, org_name VARCHAR(64) NOT NULL, parent_id BIGINT, org_code VARCHAR(32) UNIQUE ); -- 常住人口台账表:只保留派出所管控需要的必要字段 CREATE TABLE t_person ( id BIGSERIAL PRIMARY KEY, org_id BIGINT NOT NULL, id_card_no VARCHAR(18) NOT NULL, name VARCHAR(64) NOT NULL, gender VARCHAR(4), phone VARCHAR(20), address VARCHAR(256), census_house VARCHAR(256), -- 户籍地址 labels JSONB DEFAULT '[]', -- 人口标签:重点人员/独居老人/出租屋主 status VARCHAR(8) DEFAULT 'normal', -- normal/attention/missing create_time TIMESTAMP DEFAULT now(), update_time TIMESTAMP DEFAULT now() ); -- 警情表核心索引:按单位+状态+录入时间过滤,是列表查询的主要路径 CREATE INDEX idx_alarm_org_status_time ON t_alarm (org_id, status, create_time DESC);

这段 DDL 有几个设计点需要注意。org_id 是数据权限的核心字段,几乎所有业务表都带它,后续做数据过滤时只需要统一拼这个条件,不用每张表单独处理。alarm_type、source_type、status 全部用 VARCHAR 存字典编码,而不是用数字枚举,因为公安业务的字典项经常要由上级统一调整,存编码比存数字可读,改字典时也不用动历史数据。t_person 的 labels 用 JSONB,一个人可能同时有多个标签,比如既是出租屋主又是重点人员,用数组存最灵活,后面按标签筛选时可以用 JSONB 的包含操作符。

字段命名上,我习惯全小写下划线风格,和 PG 的大小写敏感约定保持一致。id_card_no、org_id 这类字段在数据交换时大概率会被上级平台直接引用,命名越贴近业务术语越好,不要自己发明一套缩写。索引只要不冲突,组合索引比多个单列索引效果好,因为列表查询主路径是“哪个单位、什么状态、什么时间范围”。

4.2 接处警登记与派单接口:用Spring Boot写第一个可交付接口

接处警登记接口的核心逻辑很简单:接收前端提交的警情信息,从登录上下文里取出当前用户,写上单位 ID 和接警人,生成警情编号,落库。重点是“从登录上下文取用户”这一步,不要在接口参数里让前端传 orgId,否则数据权限就全串了。

@RestController @RequestMapping("/api/v1/alarm") public class AlarmController { private final AlarmFacadeService alarmFacadeService; public AlarmController(AlarmFacadeService alarmFacadeService) { this.alarmFacadeService = alarmFacadeService; } @PostMapping public Result<Void> create(@RequestBody @Valid AlarmCreateReq req) { // 参数校验交给@Valid,业务逻辑全部在Service层完成 alarmFacadeService.create(req); return Result.ok(); } }
@Service public class AlarmFacadeService { private final AlarmMapper alarmMapper; public AlarmFacadeService(AlarmMapper alarmMapper) { this.alarmMapper = alarmMapper; } @Transactional public void create(AlarmCreateReq req) { // 从登录上下文取当前用户,所有持久化操作都带orgId,保证跨所数据不会串 LoginUser user = SecurityUtils.getLoginUser(); if (user == null) { throw new BizException("登录状态已失效"); } Alarm alarm = new Alarm(); alarm.setOrgId(user.getOrgId()); alarm.setAlarmNo(generateAlarmNo(user.getOrgId())); alarm.setAlarmType(req.getAlarmType()); alarm.setSourceType(req.getSourceType()); alarm.setLevel(req.getLevel()); alarm.setContent(req.getContent()); alarm.setAddress(req.getAddress()); alarm.setLon(req.getLon()); alarm.setLat(req.getLat()); alarm.setStatus("registered"); alarm.setReceiverId(user.getUserId()); // 按期反馈的截止时间,由指挥中心统一下发口径,这里直接存业务时间 alarm.setFinishDeadline(req.getFinishDeadline()); alarmMapper.insert(alarm); } private String generateAlarmNo(Long orgId) { // 常见做法:日期 + 单位编码 + 当日流水号,保证唯一且可读 return "AL" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE) + orgId + String.format("%04d", alarmMapper.countTodayByOrg(orgId) + 1); } }

需要注意的几个参数细节。finish_deadline 是后面算“按期反馈率”的关键,这个字段的赋值口径必须和上级考核口径一致,不能前端想传什么时候就传什么时候,最好在服务端统一计算。generateAlarmNo 里用 countTodayByOrg 生成流水号,在并发高时会有问题,需要加唯一约束兜底,或者直接改为数据库序列,这里只是为了展示编号规则。level 和 source_type 一定要使用字典接口下发的前端选项,不要在数据库里存死字符串,否则后续上级要求调整分类时,只能改历史数据。接口返回结构统一用 Result 包装,错误码和错误信息在 Result 里定义,方便移动端和后端联调时快速定位问题。

4.3 数据权限自动过滤:一行注解让民警只看到本所数据

数据权限过滤有两种实现路线。一种是在每个 Mapper 的 SQL 里手动写 org_id = ?,简单直观,但容易漏,新增查询接口时很容易忘记加,而且 JOIN 查询时还要注意别名。另一种是用 MyBatis 拦截器 + 自定义注解,自动在查询 SQL 上追加数据权限条件,效果统一且不会漏。我推荐第二种,因为派出所系统的角色权限比较固定,值得把机制做透。

@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface DataScope { // 是否需要按单位过滤,默认开启 boolean orgScope() default true; }
@Intercepts({ @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}) }) public class DataScopeInterceptor implements Interceptor { private final CurrentUserHolder userHolder; public DataScopeInterceptor(CurrentUserHolder userHolder) { this.userHolder = userHolder; } @Override public Object intercept(Invocation invocation) throws Throwable { // 超管或者所领导看全所数据时,不需要追加过滤条件 LoginUser user = userHolder.get(); if (user == null || user.isAllDataScope()) { return invocation.proceed(); } MappedStatement ms = (MappedStatement) invocation.getArgs()[0]; BoundSql boundSql = ms.getBoundSql(invocation.getArgs()[1]); String originalSql = boundSql.getSql(); String tableAlias = detectMainAlias(originalSql); // 给主表追加 org_id 条件;多表JOIN时必须带别名,否则会字段歧义 String filteredSql = originalSql + " WHERE " + (tableAlias.isEmpty() ? "" : tableAlias + ".") + "org_id = " + user.getOrgId(); // 构造新的BoundSql并替换参数,解析方法这里省略,逻辑不复杂但代码较长 return invocation.proceed(); } }

这段代码特意省略了 SQL 解析和参数替换的细节,因为那部分代码又长又不影响理解。核心思路是:查询执行前,找到主表的别名,拼上 org_id 条件。真正的实现里要注意几个坑:如果原 SQL 已经带 WHERE,要拼接 AND 而不是 WHERE;SQL 里有子查询时,千万别给子查询里的同名字段也拼上条件;JOIN 多表时一定要确认 org_id 字段属于哪个表别名。这些坑处理不好,轻则查询报错,重则过滤条件被绕过。拦截器做好后,所有查询接口只需要在方法上标 @DataScope 注解,民警自然只能看到本所数据,不再依赖开发人员记得写条件。

5. 派出所信息系统避坑记录:数据迁移、同步失败和没人用移动端

这一章写的是模拟项目 X 实施过程中反复遇到过的四类问题,每条都按“现象、原因、解决”来写。这些问题有一个共同点:都不是靠加服务器或优化代码能解决的,而是数据、接口、用户习惯和查询模型这些偏“软”的因素。

5.1 现象:系统上线后人口总数对不上,差了一倍

系统上线当天,内勤把新系统里的人口总数和上级下发的人口底数一对比,发现少了几万人。第一反应是迁移脚本丢数据了,查了两天发现不是丢,是重复。原因是历史台账里有大量同一个人的多条记录:有的身份证号填了,有的填的不全;有的地址写“某某路 1 栋”,另一条写“某镇某村某某号”,实际是同一个人。数据清洗时只做了简单的去空格,没有按身份证号统一去重,结果两个人变四个人,总数自然对不上。

解决这个问题不能靠上线后手工改。正确做法是迁移前做三轮清洗:第一轮以身份证号为准去重,重复的按更新时间保留最新一条;第二轮对身份证号为空或明显的 15 位旧证做标注,不直接删除,先入“待核实”表;第三轮统一地址格式,把“某路”和“某大街”这类写法归到标准地址表。迁移后还要跑对账脚本,周期性比对系统人数和上级底数,差异落在可控范围内再宣布上线完成。

-- 迁移后必跑的重复检查:找出同一身份证号在台账里出现多次的记录 SELECT id_card_no, count(*) AS dup_cnt FROM t_person WHERE org_id = :orgId AND id_card_no <> '' GROUP BY id_card_no HAVING count(*) > 1; -- 必填缺失检查:电话、地址为空的人口记录,往往是历史数据没录全 SELECT id, name, id_card_no, phone, address FROM t_person WHERE org_id = :orgId AND (phone = '' OR address = '');

5.2 现象:凌晨同步任务报了成功,上级平台却查不到数据

系统上线第一周,每天凌晨跑一次向上级平台的数据同步,任务日志显示成功,但上级平台里就是查不到当天的警情。后来看实际响应,才知道批量接口是“整批失败”模式:本地这批 200 条警情里,有一条的警情编号长度超出了对方字段定义,对方直接把整批都拒了,但返回体里错误信息写得不明显,同步工具只看 HTTP 状态码,200 就当成功。

这个坑的教训是:所有对外同步必须做“逐条校验、逐条确认、失败重试”。本地在组装批量数据前,先按对方的字段约束跑一遍校验规则,把超长、空值、非法枚举值过滤掉;同步接口要能拿到逐条的返回结果,有一条失败就单独记到同步失败表里,第二天重试,而不是让整批重来。另外,重试一定要做幂等,对方接口支持按业务主键去重就尽量利用,避免重复数据把对方库搞乱。血泪经验是:上线前一定要找对方要一份“校验手册”,哪怕是 PDF,也比自己在联调时猜字段长度强。

5.3 现象:值班民警宁可手写接警单,也不用移动端录入

新系统的移动端上线两周,后台日志显示登录次数寥寥无几。去值班室蹲了一晚才发现问题:民警接一个报警电话,在警务通上要点七八次屏幕,警情类型、来源、当事人、地址、内容、备注全是必填项,表单还是两列布局,单手根本够不到。相比之下,纸质接警单写三个关键字就完事,等有空再补录。民警的原话是“系统是给内勤用的,不是给出警人用的”。

解决这个问题的关键是做“快速录入模式”,移动端和 Web 端的表单完全分离。快速录入模式只保留三个必填:警情类型、发生地址、警情内容。地址用地图选点回填,不用手敲;内容支持语音转文字;当事人信息不强制,回到所里再补。同时把“回所补录”做进业务流程里,交接班时值班民警必须确认当班警情都补录完整才能下班。改造之后,录入率才真正上来。不要指望靠培训和行政命令解决产品设计问题,工具难用就是难用,一键录入比什么激励都管用。

5.4 现象:人口查询页面点一下要等十几秒

人口台账上线前都好好的,上线一个月后内勤反映页面越来越慢,按姓名查一个人要转十几秒。看执行计划发现,查询 SQL 被写成了 WHERE org_id IN (…) AND name LIKE '%张三%',前后百分号的模糊匹配让索引直接失效。再加上列表页默认不带任何筛选条件,内勤打开就是全所人口全表扫描,慢是必然的。

修复分三步走。第一步,所有关键字查询改成前缀匹配,姓名、地址这种字段不再支持前后模糊,必要时配合拼音首字母列来优化体验。第二步,组合索引补齐到(org_id, name)、(org_id, status, create_time DESC)。第三步,列表查询强制带单位过滤和时间范围,哪怕是默认最近三个月,也不允许一次拉全量。改完之后,页面响应回到两秒以内。这事的教训是:派出所数据量再小,也不能写出全表扫描的查询,索引设计和查询习惯要从第一天就立好规矩。

6. 让系统真正被用起来:每日数据质量自检和月度报表自动化

系统上线不是终点,真正让它在所里立住脚的是日常数据能不能变成领导看得见的成果。我最常用的做法是写一组数据质量自检脚本挂在定时任务里,每天凌晨跑,早上八点把结果推给内勤。脚本查的东西很简单:身份证号重复、人口无联系电话、警情超过 24 小时还停在“已派单”、重点人员半年没有一条走访记录。规则不追求一次做全,每个月根据业务反馈加一两条,比憋大招更可持续。

-- 月度接处警统计:按所统计警情总量、按期反馈量和反馈率 SELECT org_id, to_char(create_time, 'YYYY-MM') AS month, count(*) AS total_alarms, count(*) FILTER ( WHERE finish_time IS NOT NULL AND finish_time <= finish_deadline ) AS ontime_alarms, round( 100.0 * count(*) FILTER ( WHERE finish_time IS NOT NULL AND finish_time <= finish_deadline ) / NULLIF(count(*), 0), 2 ) AS ontime_rate FROM t_alarm WHERE create_time >= date_trunc('month', now()) - interval '6 month' GROUP BY org_id, to_char(create_time, 'YYYY-MM') ORDER BY month DESC;

这条反馈率 SQL 是月报最核心的指标,直接反映接处警处置时效。前提是 finish_deadline 入库时有统一口径,口径不定,SQL 再漂亮也是白搭。我习惯把这类统计做成模板文件,每周一跑一次,导出 Excel 给所领导看,代替人工导数调格式。还有一个技巧:月报维度尽量和上级考核口径对齐,按期反馈的时间口径必须一致,否则自己算的 98% 和上级通报的 85% 对不上,每次开会都很被动。数据自检发现异常,先补数据再改代码,补数要有审批记录,防止说不清。做这个系统大半年,我最深的体会是功能代码只占一半精力,另一半全在数据和口径上。把这两件事抓住,系统才算真正用起来了。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 10:17:44

ponytail插件实战:用束拢思路统一管理零散配置与任务

1. 从“ponytail”这个标题说起&#xff1a;它到底是什么第一次看到“ponytail”这个词&#xff0c;很多人脑子里蹦出来的画面大概是扎起来的马尾辫。但在技术圈和工具链语境里&#xff0c;ponytail 早就不是发型那么简单了。它更像是一种“把散落的东西收拢、束紧、统一管理”…

作者头像 李华
网站建设 2026/10/15 10:17:19

Java万年历源码:闰年判断与蔡勒公式实现详解

简介&#xff1a;这是一份面向Java初学者和课程设计学生的完整“万年历记事本”项目资料&#xff0c;以Swing图形界面实现万年历展示和日记记录功能&#xff0c;是学习日期时间处理、GUI组件布局、事件驱动编程及文件读写的综合案例。压缩包内仅含1个doc文档&#xff0c;大小31…

作者头像 李华
网站建设 2026/10/15 10:15:21

S32K3xx车规MCU数据手册精读:从Cortex-M7架构到量产选型避坑指南

简介&#xff1a;S32K3xxDS.pdf 是 NXP S32K3xx 系列微控制器的官方数据手册&#xff0c;面向汽车电子、工业自动化领域的嵌入式软硬件工程师及高校相关专业学习者&#xff0c;用于快速掌握该系列芯片的规格参数与选型依据。资源包仅含 1 个 PDF 文件&#xff0c;大小约 5.14MB…

作者头像 李华
网站建设 2026/10/15 10:15:07

基于ThinkPHP与Laravel的医疗健康小程序开发实践

1. 项目背景与核心价值最近在帮本地一家社区医院做数字化升级时&#xff0c;发现他们原有的挂号系统存在几个痛点&#xff1a;患者需要在上班时间打电话预约、现场排队时间长、医生号源分配不合理。于是我们决定基于微信小程序开发一套健康管理系统&#xff0c;整合挂号预约、健…

作者头像 李华