首页 > 数据库 >SQL进阶技巧:如何生成一个员工及其有效门禁卡的列表?

SQL进阶技巧:如何生成一个员工及其有效门禁卡的列表?

时间:2025-01-01 11:28:08浏览次数:3  
标签:进阶 门禁卡 issued emp SQL date badge id

目录

0 需求描述

1 数据准备

2 问题分析

方法1:使用窗口函数row_number()

方法2:采用case when 

3 小结

往期精彩


0 需求描述

  1. 目标:生成一个员工及其有效门禁卡的列表。
  2. 规则
    • 员工可能有多个门禁卡。
    • 每个员工在同一时间只能有一个有效的门禁卡。
    • 默认最新的门禁卡是有效的(因为是在新工作场所发出的)。
    • 门禁卡号是随机的。
    • 用 A 表示门禁卡有效(active),I 表示失效(inactive)。

1 数据准备

1、创建用户表
create table personnel
( emp_id integer not null primary key ,
emp_name char ( 30 ) not null
)
--2、创建门禁卡状态表
create table Badges
(
badge_nbr integer not null primary key ,
emp_id integer not null references personnel ( emp_id ),
issued_date date not null,
badge_status char ( 1 ) not null check ( badge_status in ( 'A' , 'I' )),
)
--3、插入初始化数据
insert into personnel ( emp_id , emp_name )
values ( 1 , 'Backer' ),( 2 , 'Tal' ),( 3 , 'Cak' ),( 4 , 'Dake' )                                         
insert into Badges ( badge_nbr , emp_id , issued_date , badge_status )
values ( 1 , 1 , '2017-11-08' , 'A' ),
( 2 , 1 , '2017-11-09' , 'A' ),
( 3 , 1 , '2017-11-10' , 'A' ),
( 4 , 1 , '2017-11-11' , 'A' ),
( 5 , 1 , '2017-11-12' , 'A' ),
( 6 , 1 , '2017-11-13' , 'A' ),
( 7 , 2 , '2017-11-08' , 'A' ),
( 8 , 2 , '2017-11-09' , 'A' ),
( 9 , 2 , '2017-11-10' , 'A' ),
( 10 , 3 , '2017-11-08' , 'A' ),
( 11 , 3 , '2017-11-09' , 'A' ),
( 12 , 4 , '2017-11-08' , 'A' )

2 问题分析

方法1:使用窗口函数row_number()

-- 使用窗口函数和子查询为每个员工的门禁卡分配一个行号,最新的为 1
WITH RankedBadges AS (
    SELECT 
        badge_nbr, 
        emp_id, 
        issued_date, 
        badge_status,
        ROW_NUMBER() OVER (PARTITION BY emp_id ORDER BY issued_date DESC) AS rn
    FROM Badges
)
-- 更新门禁卡状态,将最新的设为 'A',其余设为 'I'
SELECT 
    badge_nbr,
    emp_id,
    issued_date,
    CASE WHEN rn = 1 THEN 'A' ELSE 'I' END AS badge_status
FROM RankedBadges;

方法2:采用case when 

-- 创建临时表存储每个员工的最新门禁卡的 issued_date
with LatestBadges AS
(SELECT 
    emp_id, 
    MAX(issued_date) AS latest_issued_date
FROM Badges
GROUP BY emp_id) 

-- 更新门禁卡状态,将最新的设为 'A',其余设为 'I'
SELECT 
    b.badge_nbr,
    b.emp_id,
    b.issued_date,
    CASE WHEN b.issued_date = lb.latest_issued_date THEN 'A' ELSE 'I' END AS badge_status
FROM Badges b
JOIN LatestBadges lb ON b.emp_id = lb.emp_id;

3 小结

如果有多个员工在同一天发放门禁卡,该如何处理? 

 如果你希望将同一天发放的多个门禁卡都标记为有效,可以使用 DENSE_RANK() 函数替代 ROW_NUMBER() 函数。DENSE_RANK() 函数会给相同的数据分配相同的排名,并且排名是连续的,不会跳过任何排名。以下是修改后的代码:

-- 使用 DENSE_RANK 函数更新门禁卡状态
WITH RankedBadges AS (
    SELECT 
        badge_nbr,
        emp_id,
        issued_date,
        badge_status,
        DENSE_RANK() OVER (PARTITION BY emp_id ORDER BY issued_date DESC) AS rn
    FROM Badges
)
UPDATE Badges b
JOIN RankedBadges rb ON b.badge_nbr = rb.badge_nbr
SET b.badge_status = CASE 
                      WHEN rb.rn = 1 THEN 'A' 
                      ELSE 'I' 
                  END;

或者

-- 使用窗口函数更新门禁卡状态,将同一天发放的都标记为有效
WITH RankedBadges AS (
    SELECT 
        badge_nbr,
        emp_id,
        issued_date,
        badge_status,
        CASE 
            WHEN issued_date = MAX(issued_date) OVER (PARTITION BY emp_id) THEN 'A'
            ELSE 'I'
        END AS new_badge_status
    FROM Badges
)
UPDATE Badges b
JOIN RankedBadges rb ON b.badge_nbr = rb.badge_nbr
SET b.badge_status = rb.new_badge_status;



往期精彩



数仓建模:什么是全量表,增量表,快照表,拉链表,流水?

指标体系建设:如何理解指

指标体系建设:如何进行自下而上的指标收集?

指标体系构建:如何设计北极星指标设计?

指标体系建设:如何进行自上而下的指标拆解?

 

如果您觉得本文还不错,对你有帮助,那么不妨可以关注一下我的数字化建设实践之路专栏,这里的内容会更精彩。

专栏 原价99,现在活动价59.9,按照阶梯式增长,还差5个人上升到69.9,最终恢复到原价

 

专栏优势:
(1)一次收费持续更新。

(2)实战中总结的SQL技巧,帮助SQLBOY 在SQL语言上有质的飞越,无论你应对业务难题及面试都会游刃有余【全网唯一讲SQL实战技巧,方法独特】

(3)实战中数仓建模技巧总结,让你认识不一样的数仓。【数据建模+业务建模,不一样的认知体系】(如果只懂数据建模而不懂业务建模,数仓体系认知是不全面的)

(4)数字化建设当中遇到难题解决思路及问题思考。

我的专栏具体链接如下

数字化建设通关指南_莫叫石榴姐的博客-CSDN博客

https://blog.csdn.net/godlovedaniel/category_12706766.html

标签:进阶,门禁卡,issued,emp,SQL,date,badge,id
From: https://blog.csdn.net/godlovedaniel/article/details/144852844

相关文章

  • C进阶-字符串与内存函数介绍(另加2道典型面试题)
    满意的话,记得一键三连哦!我们先看2道面试题第一道:我们画图理解: pa++,先使用再++,pa开始指向a【0】,++之后pa向下移动一位,再解引用,指向a【1】,a【1】又指向at的首元素a的地址,开始打印字符串at第二道:我们画个图:(初始的指向图)第一个printf:(配着图哦!)(注意上一个printf的图......
  • Linux 虚拟机环境安装(jdk/mysql/redis/tomcat/nginx/挂载)
    =================================================================准备工作=================================================================yuminstallwgetyuminstall-ygcc-c++pcrepcre-develzlibzlib-developensslopenssl-develyuminstallchkconfi......
  • commsqlplus 数据库dba开发工具(二)
    帮助和连接信息(日后支持多种数据库,通用命令管理不同数据库) 查看参数:收集统计信息,查看表信息查看数据: 执行计划直接输出 帮忙在信息和status ......
  • commsqlplus 数据库dba开发工具(一)
    PG数据库,输出oracle格式的执行计划: 继续输出分析计划必要信息:执行过程中的活动监控:sqltext有三个pid  PG自有工具格式输出 ......
  • sql server 存储过程
    SQLServer存储过程笔记什么是存储过程(StoredProcedure)存储过程是预编译的SQL语句集合,存储在SQLServer数据库中,可以通过名称调用。它们通常用于执行复杂的操作、数据验证、错误处理或批量数据操作。存储过程可以接受输入参数,执行一系列的SQL操作,并返回结果或状态......
  • JAVA开源毕业设计 大学生竞赛管理系统 Vue.JS+SpringBoot+MySQL
    本文项目编号T101,文末自助获取源码\color{red}{T101,文末自助获取源码}......
  • JAVA开源毕业设计 租房管理系统 Vue.JS+SpringBoot+MySQL
    本文项目编号T102,文末自助获取源码\color{red}{T102,文末自助获取源码}......
  • SQL优化| IS NOT NULL 优化与 NOT NULL 查询慢优化
    在SQL查询时,SQL语句中由于使用了ISNOTNULL,导致查询时间过长,数据表有180W条数据,查询的字段上已经有普通索引,我们使用简单的sql查询这个cfErpPayNumber不是空的记录,耗时需要1843ms,这是非常头疼的,  查看执行计划,是全表扫描这里为了加快查询效率,我们需要加入函数索引, ......
  • 不再担心安装问题!手把手教你在 CentOS 上安装 MySQL 8
    目录......
  • Flutter进阶组件(7):DataTable(数据表格)
    DataTable是一个用于展示数据的表格组件,它允许开发者以一种结构化和可滚动的方式展示数据集。DataTable非常适合展示详细信息,如表格数据、统计数据或配置选项。一、创建基本的DataTable以下是创建一个基本DataTable的示例:import'package:flutter/material.dart';voidmain()......