基於MySQL+PHP的羽毛球費用查询网站设计
问题来源
我们有一个羽毛球小组,不定期组织打球,会产生场地费和球费,每次收钱特别琐碎,所以组长(现任组长其实就是我)每次开学就让大家先交100块,然后记账再从交的费用里面扣。前任组长专业是CS的(其实现任组长也是,也就是我),他设了一个网站(其实是学校的一个服务器),但是这个网站是基于XML的,每次更新都要打开XML文件一项一项地更新,而且还要自己计算每个人的费用。在前任组长把工作转交给我之后我第一件事就是对网站改版,因为作为程序员,简单重复性工作真的是不能忍的事!
但其实我没学过网页编程,不会Javascript和PHP,但是我懂数据库呀!我会C++啊!秉着天下语言源出一宗的思想,我想只要会一种语言,其它都应该是很容易学的吧!结果根本不是……没有网络基础这些语言真的好难学……难虽然难,但还是设计出了一个简易的网站让我可以在网页上更新费用,让大家可以在网页上查询羽球小组的财务状况。服务器用的是实验室的NAS.
需求
羽球小组大概有二十多个人,每年都有新进成员,也有人退出(毕业了),每学期大概缴费一次。每次活动产生的费用包括球费和场地费,这些费用由所有参加活动的成员平摊。
因此这个数据库需要记录:
- 小组成员信息
- 成员每次缴费的信息
- 每次活动产生的费用
- 每次活动参加的人员
小组成员可以:
- 查询每次活动的费用记录
- 查询每次活动的出席人员
- 查询自己会费的余额
- 查询自己的缴费记录
我要:
- 输入每次活动的日期
- 输入每次活动参加的人员
- 输入每次活动的费用
设计
根据上述需求,该业务的ER图如下。为了充分满足数据库设计的范式要求,设计了三个实体,两个关系,所以一共要有五张表。下图的设计至少满足第二范式(2NF),是否满足第三范式呢?仔细看了一下,好像满足。若要满足更高的范式,就需要拆分更多的表,SQL语句也会更复杂。注意到下图中没有一张表会存储『某个组员在一次球事中花费了多少钱』这样的信息,也没有『某个组员的会费余额是多少』这样的信息。因此查询这样的信息时SQL语句会稍微复杂一点,但这样的设计会减少表的信息冗余。
数据库搭建
数据库使用的是MySQL。Mac上推荐MyAdmin套件,Ubuntu上推荐phpMyAdmin套件。各种设置都设定好了,可以让人直接关注业务。根据以上ER图,设计了五张表,名称分别为:
- memeber_t
- memact_t(对应Attend)
- activity_t
- fee_t
- memfee_t (对应Pay_Fee)
整个网站搭设在实验室的NAS上。NAS真是个好东西,写好后直接往上一丢即可。
编码工作与SQL语句编写
数据库的设计不难,难的是网页查询展示的工作以及SQL语句的编写。这个网站后台用的是PHP语言。但我用PHP的时候被实验室的人鄙视了……觉得PHP太古老,应该用Ruby。
在编写网站时用到了AJAX技术,但其实AJAX不是我的研究重点,所以这篇文章先略过吧……
下面给出5张表的截图,针对实际的查询需求编写一些SQL语句。
member_t
activity_t
memact_t (对应Attend)
fee_t
memfee_t (对应Pay_Fee)
发现fper_income这个字段表示组员交的会费。发现这个字段中有负数?负数的意思就是退钱给组员,使得总结余为0. 通常是毕业的组员这个字段会出现负数。
所有的查询都是根据姓名来查询,姓名对应member_t表中的name字段。下图是这个网站的查询页面(还有个管理页面)截图,很丑,实验室的人看到只有一片揶揄……不过初始目的和主要功能都满足了,作为一个功能性的网站,就不要太注重外观了。
- 根据姓名(name)查询该组员参加的所有打球场次的信息,包括打球日期,场地费,球费,该场次的人数,该组员应付的费用,打球举办的场所(INNER JOIN)
上述查询横跨三张表的信息,因此需要连接三张表。该组员应付的费用意思是场地费加上球费再除以参与打球的人数。但是有时候有些会员会带朋友来打球,而那位朋友不在系统里,所以这个会员此时就要帮他朋友支付费用,因此在memact_t表中会多出一个adj_balance的字段。
实际操作中在后台并不是根据姓名来查询,而是根据member_t.mid字段(主键)来查询。假设已经知道user_id,SQL语句如下:
SELECT A.adate, A.asite_fee, A.aball_fee, A.aperson_num, A.aplace, B.adj_balance, (A.asite_fee+A.aball_fee)/A.aperson_num + B.adj_balance
FROMactivity_t AS A, memact_t AS B
WHEREmemact_t.mid = user_id
ANDmemact_t.aid = activity_t.aid
上述SQL语句实际是INNER JOIN操作,也可以使用INNER JOIN关键字将上述语句改写成下面的形式:
SELECT A.adate, A.asite_fee, A.aball_fee, A.aperson_num, A.aplace, memact_t.adj_balance
FROM activity_t AS A
INNER JOIN memact_t ON memact_t.aid = activity_t.aid
AND memact_t.mid = 2
- 根据姓名(name)查询该组员的缴费记录,包括缴费日期,每次缴费的费用(INNER JOIN)
上述操作仍然是INNER JOIN操作,SQL语句如下:
SELECT memfee_t.fper_income, fee_t.date
FROM memfee_t, fee_t
WHERE memfee_t.mid = user_id AND memfee_t.fid = fee_t.fid
这段SQL也可以改写成用关键字INNER JOIN的形式。
- 根据姓名(name)查询该组员的费用结余以,总缴费与总支出
一个会员的费用结余 = 总缴费 - 总支出。总缴费和总支出都没有直接记录在表中,横跨四张表,要将这三个结果同时写到一个SQL语句有点复杂……所以实际的编码中是分开写成两个SQL语句,一个是总缴费,一个是总支出。
总缴费:
SELECT SUM(memfee_t.fper_income) FROM memfee_t WHERE mid = user_id
总支出:
SELECT SUM((A.asite_fee + A.aball_fee) / A.aperson_num + B.adj_balance)
FROMactivity_t AS A, memact_t AS B
WHEREB.mid = user_id AND A.aid = B.aid
- 根据日期查询这天参加打球的组员名单(IN语句)
上述查询需要用到IN语句。IN语句可以在WHERE字句内指定多个值,很好用。下面是这个查询的SQL语句,用了两个IN语句,第一个IN字句中嵌套了第二个IN。原因是因为同一个日期有可能会返回多个activity_aid(就是一天打了不止一场球)。
SELECT member_t.chname
FROM member_t
WHERE member_t.mid IN (SELECT memact_t.mid FROM memact_t WHERE memact_t.aid IN (SELECT activity_t.aid FROM activity_t WHERE activity_t.adate = '2015-03-14'))
写本文的动机
这个网站在我入学的时候就写好了,现在已经差不多过去两年了。因为需要将工作转交给下一任组长,因此需要将整个网站一起移交。所以需要有一份文档记录。同时,因为面试总是会被问到SQL语句的问题。当初写这个网站时查询了很多SQL语句的写法,但作为一个比较『激进』的实验室,大家都不太喜欢传统的关系型数据库,所以很久不用会忘记,每次面试我的回答都是『需要用的时候我会查』。感觉这个答案不太好,所以写这篇文章也是为了复习一下SQL的语法……
另外一直想在改进一下这个网站。目前主要功能还是查询,其实是为了公示每次打球的费用,没有线上自动交费的功能,如果线上自动线上交费我也就不用那么辛苦每个人收钱了……
基於MySQL+PHP的羽毛球費用查询网站设计相关推荐
- 基于java旅游网站设计计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署
基于java旅游网站设计计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署 基于java旅游网站设计计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署 本源码技术栈: 项目架构 ...
- quartus ii matlab,基於Quartus II和MATLAB的FIR濾波器設計與仿真(二)
接上文 基於Quartus II和MATLAB的FIR濾波器設計與仿真(一): 3 QuartusII 調用 IP 核生成 FIR 濾波器模塊 在 Quartus II 中, Altera 提供了 ...
- 基於IIS的WCF的分布式多層架構開發實現
曾用.NET Remoting,基於IIS,為公司實現過分布式多層架構,客戶端采用Web Browser瀏覽,當時,公司領導告訴我可能會有多臺中間服務器用於系統,又不想每臺電腦的去安裝程序,所以,我最 ...
- python笑傲江湖统计字数_基於Python的tf-idf算法实现:以《笑傲江湖》为例
连结Jasonnor/tf-idf-pythongithub.com 简介 tf-idf(term frequency-inverse document frequency)是一种用於信息检索与文字 ...
- php complex,PHP復雜的基於角色的訪問控制列表
I have already made the database and the php code needed to implement this customized ACL system. No ...
- linux下复制catalog信息指令,基於Linux下catalog方式的 Oracle 備份策略(RMAN)
--********************************** --基於Linux下 Oracle備份策略(RMAN) --********************************* ...
- python 读取qq群消息_基於Python自動發送QQ群消息
1.准備工作 此次測試基於python3,需要安裝qqbot.bs4.requests庫. qqbot項目地址:https://github.com/pandolia/qqbot.git pip qq ...
- mt7601的linux驱动下载,mt7601u,基於 Linux mac80211 MT7601U USB bgn無線dongle驅動程序,下載mt7601u的源碼_GitHub_開發99...
這是一款用於 MT7601U USB dongle的Linux驅動程序. 它是基於供應商gpl驅動程序從頭開始編寫的. 供應商驅動程序不同,這個驅動程序使用現代的Linux WiFi基礎設施,並且應該 ...
- netty框架android,隻需五步,即可基於Netty框架實現Android內網推送功能。
隻需五步,即可基於Netty框架實現Android內網推送功能. 一.先引入依賴,客戶端和服務端用的都是同一個依賴netty-all. Android Studio中Gradle配置: compile ...
最新文章
- 奇葩错误:cv.imread()读取失败
- MySql The service could not be started
- 持币过节也能让钱生钱
- aidl demo调用原理
- mysql单表备份语句 +多表
- java之Stack详细介绍
- 腾讯再出新招!社交新产品“有记”已上线?
- 读程序员网游专题云风的文章有感
- SQL Server高级查询之子查询(在DML语句中使用子查询)
- (转) 穿越NAT总结
- MFC 的几个常用函数,用来计算文件大小,下载速度,转换时间的
- 纯虚函数的类为什么不能被实例化
- 转换PDF技巧1之PDF虚拟打印机操作详解
- SIM868模块+Arduino将位置信息上传到服务器
- 神秘的程序员头像包(附口罩版)第一发
- Linux/Windows快速镜像安装包下载
- 计算机快捷方式后缀名,win10系统去掉“快捷方式”四个字后缀名的操作方案
- Fedora 17下NVIDIA双显卡闭源驱动的安装
- 正则表达式中的特殊字符一览
- hdu5172 GTY‘s gay friends(hash判断排列)