求一sql语句!!高手帮帮忙

mydreamf 2008-03-12 05:49:01
有两个表
表1、配置预约的表,表2、已经预约的表
表1的字段。id,预约项目,预约名额,时间
表2的字段。ID,预约的人,预约的项目
表1、假设数据
id,预约项目,预约名额,时间
1,洗剪吹,2,12:00
2,染头发,3,12:00

在申请预约的时候,有一个页面根据时间显示出,当前可以预约的项目,
假设 洗剪吹已预约2人,染头发已预约2人。那么只剩下一个名额是染头发得。那么我在选择预约项目的时候,只能选择染头发。洗剪吹就不能选了。
假设 洗剪吹已预约1人,染头发已预约2人。那么就可以选择洗剪吹和剪头发两个项目

求一sql可以筛选出,预约名额未满的项目
...全文
242 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
mydreamf 2008-03-14
  • 打赏
  • 举报
回复
[Quote=引用 30 楼 yangpeiyu 的回复:]
楼主。你根本都是乱来。给分都乱给。
再说给你点评一下上面那兄弟my22xo 这个人的SQL效率都会很大的问题。not in 当你数据多就能休现出来。
小题大做。没话说。。
[/Quote]

1、首先my22xo,即时帮我解决了问题。
2、我也明白not in的效率问题。我的数据并不多,撑死也没有100条,所有用not in.
3、你提供的方法我的实际情况解决不了,因为我知道a.预约名额,并不知道b.的已预约名额,这个算法。是根据my22xo的提示,我自己试出来。
yangpeiyu 其实分数没啥。主要是否解决了问题。
您的建议,我下次注意。
望你海涵
骑蚊子旅游 2008-03-13
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 mydreamf 的回复:]
my22xo 和yangpeiyu
不知道是不是我的问题,如果在预约表里面某个项目没有被预约那么,查出来的结果,都是不对的。
[/Quote]


兄弟,把语句改成这个:

select 预约项目表.itemname from 预约项目表 inner join 预约表 on 1=1 where 预约项目表.itemNum not in (select count(预约表.ID) from 预约表 where 预约表.itemid=预约项目表.id group by 预约表.itemID) group by 预约项目表.itemname

mydreamf 2008-03-13
  • 打赏
  • 举报
回复
郁闷阿,脑袋打结了。。。
mydreamf 2008-03-13
  • 打赏
  • 举报
回复
my22xo 和yangpeiyu
不知道是不是我的问题,如果在预约表里面某个项目没有被预约那么,查出来的结果,都是不对的。
mydreamf 2008-03-13
  • 打赏
  • 举报
回复
哈哈,我来拉!感谢my22xo 和yangpeiyu。
我根据你们的算法来弄弄看,回来给你们分。
yangpeiyu 2008-03-13
  • 打赏
  • 举报
回复
楼主。你根本都是乱来。给分都乱给。
再说给你点评一下上面那兄弟my22xo 这个人的SQL效率都会很大的问题。not in 当你数据多就能休现出来。
小题大做。没话说。。
mydreamf 2008-03-13
  • 打赏
  • 举报
回复
加入筛选条件后,程序完美执行!
感谢my22xo的赐教!马上结贴
骑蚊子旅游 2008-03-13
  • 打赏
  • 举报
回复
我倒,呵呵。

得加分才行,哈哈


select 预约项目表.id,预约项目表.itemname from 预约项目表 inner join 预约表 on 1=1 where 预约项目表.itemNum not in (select count(预约表.ID) from 预约表 where 预约表.itemid=预约项目表.id group by 预约表.itemID) group by 预约项目表.itemname,预约项目表.id order by 预约项目表.id
mydreamf 2008-03-13
  • 打赏
  • 举报
回复
嗯,我详细看看。
我按照你的思路,写出来了。发现一个问题
由于在主语句使用了group by group by 预约项目表.itemname
所以我无法得到。当前洗剪吹的项目的id,我只知道了。还剩下的预约项目的名字,然而在预约表的情况下,我需要存入对应的id
骑蚊子旅游 2008-03-13
  • 打赏
  • 举报
回复
预约表.itemid=预约项目表.id 的作用是这样的,由于预约项目表.itemnum不是唯一的,用select count(预约表.ID) from 预约表 group by 预约表.itemid 查询出来的值比如可能是6,3,2,1 而主语句itemnum就会产生和结果为6的itemid关联,还会和结果为3的itemid关联,查出的结果就不准确。由于两个表在主语句中已经inner join进行了联接,所以加个限制条件“预约表.itemid=预约项目表.id”就可防止数据重复。

这个不好表达,把结果都列出,举个实例吧
(预约项目表)select id,itemname,itemnum from 预约项目表 (把这个假设称为A查询)
1 洗剪吹 6
2 染头发 3
3 拉头发 2
4 测试1 2
5 测试2 3
6 测试3 9

select itemid,count(预约表.ID) from 预约表 group by 预约表.itemID (把这个假设称为B查询)
1 5
2 3
3 1
4 2

我们可以看到A查询洗剪吹是6个名额,在B查询中对应的项目ID(洗剪吹的ID是1,B查询中的ITEMID=1的已登记名额为5,则剩余1个名额),有1个空余名额,但由于使用关键字not in,所以在B查询中的每一个结果都符合洗剪吹的空余名额(全部小于洗剪吹的6个名额),这样结果就肯定不正确了,同时满足染头发这个项目的在B查询中有3和4,都小于染头发的总名额,光这两个项目统计出来就有6个,所以在主语中用了inner join 语句,这时候在子查询中加个限制条件,即A查询中的ID和B查询中的itemid对应的统计出来(比如洗剪吹的ID1与B查询中的ID1对应起来,不对应的不选择出来),这样才是正确的对应关系。不知道这样讲解你是否明白?明白了的话望楼主加点分,呵呵。谢谢
mydreamf 2008-03-13
  • 打赏
  • 举报
回复
稀里糊涂,既然写出来了。给自己一把掌先
mydreamf 2008-03-13
  • 打赏
  • 举报
回复
my22xo
select count(预约表.ID) from 预约表 where 预约表.itemid=预约项目表.id group by 预约表.itemID
这句话的意思是?
为什么是where 预约表.itemid=预约项目表.id
这个不可能相等把,就是为了不想等吗?
fcxxfcxx 2008-03-12
  • 打赏
  • 举报
回复
up
ccaakkee 2008-03-12
  • 打赏
  • 举报
回复
mark
骑蚊子旅游 2008-03-12
  • 打赏
  • 举报
回复
我刚特意测试了一下

把下面的SQL代码直接放到查询分析器里面执行,就可以显示出结果了。

呵,结分:)


create table 预约项目表
(
id int identity(1,1),
itemName varchar(20) default '',
itemNum int default 0,
itemDateTime datetime default getdate()
)


create table 预约表
(
id int identity(1,1),
itemID int default 0,
personName varchar(20) default '',
)

insert into 预约项目表(itemName,itemNum) values('洗剪吹',6)
insert into 预约项目表(itemName,itemNum) values('染头发',3)
insert into 预约项目表(itemName,itemNum) values('拉头发',2)

insert into 预约表(itemID,personName) values(1,'张三')
insert into 预约表(itemID,personName) values(1,'张四')
insert into 预约表(itemID,personName) values(1,'张四')
insert into 预约表(itemID,personName) values(1,'张五')
insert into 预约表(itemID,personName) values(1,'张五')
insert into 预约表(itemID,personName) values(2,'李一')
insert into 预约表(itemID,personName) values(2,'李二')
insert into 预约表(itemID,personName) values(3,'王老一')
insert into 预约表(itemID,personName) values(3,'王老二')



select * from 预约项目表
select * from 预约表
select count(预约表.ID) from 预约表 group by 预约表.itemID

select 预约项目表.itemname from 预约项目表 where 预约项目表.itemNum not in (select count(预约表.ID) from 预约表 group by 预约表.itemID)

骑蚊子旅游 2008-03-12
  • 打赏
  • 举报
回复
试试我的SQL,按不同的项目ID(建议用ID,因为用名字的话有时候若改了项目名字会导致查询结果不正确)分组统计出一共有多少人已经预约,然后看一下项目的预约名额,若统计的结果和预约名额相等,说明预约名额已经满了,所以用了not in,表示预约未满的名额的项目全部查找出来了。

mydreamf 2008-03-12
  • 打赏
  • 举报
回复
ok,下班了。。明天回来结贴!
骑蚊子旅游 2008-03-12
  • 打赏
  • 举报
回复
建议表2的字段加一个字段项目ID,以便和表1的ID值关联

select 表1.预约项目 from 表1 where 表1.预约名额 not in (select count(表2.ID) from 表2 group by 表2.项目ID)


如果要做时间判断的话,表2里面也要加上别人预约的时间字段,然后在上面的语句里面把时间条件放进去就可以了。

yangpeiyu 2008-03-12
  • 打赏
  • 举报
回复
嗯。可以的。你照改就可以的啦。记得给分哦。哈。
mydreamf 2008-03-12
  • 打赏
  • 举报
回复
我试试看,这样好像差不多。。。
加载更多回复(10)
jdbc: 1.数据库连接的方式: ODBC:开放式数据库连接。 C语言实现的,提供语言和(基于SQL的)数据库进行交互的“一致性”的接口 JDBC:java版本的ODBC JDBC连接数据库的步骤: 1.注册驱动(加载驱动): 注册的方式: 1.使用类加载器(使用反射的方式) Class.forName(driverName); 2.实例化Driver Driver driver = new oracle.jdbc.driver.OracleDriver(); DriverManager.registerDriver(driver); 3.加虚拟机参数jdbc.drivers -Djdbc.drivers=oracle.jdbc.driver.OracleDriver 4.从Jdk6.0以后要求,JDBC 4.0 Drivers 必须包括 META-INF/services/java.sql.Driver 文件,有了这个文件以后不需要在显示的使用Class.forName来进行驱动的注册 Oracle数据库进行连接的时候,使用的驱动类: 1.oracle.jdbc.driver.OracleDriver 2.oracle.jdbc.OracleDriver 2.建立连接 连接方式: 1.DriverManager(中的getConnection其实也是调用的Driver.connect方法) getConnection(url);//没有用户名密码 //将用户名密码存放在java.util.Properties对象中 getConnection(url,properties); getConnection(url,user,passwd); 2.直接调用Driver.connect方法执行 Driver d = new DriverClass(); d.connect(url,properties); 3.创建Statement: Statement: 1.创建时不需要传递sql语句,但是执行时需要传递sql语句 2.如果涉及到动态参数的传递,必须使用字符串拼接 PreparedStatement: 1.创建时就需要传递sql语句,执行的时候不需要传递sql语句 2.如果涉及到动态参数的传递,可以使用字符串拼接,也可以使用?占位的形式 给?号传值使用的是 pstmt.setType(index,value); index从1开始 3.提供预编译的功能,某种程度上可以避免sql注入的问题 4.提前做语法检查,在给?赋值的过程中要求数据类型一定要匹配,这样在某种程度上可以避免因为数据类型不匹配而发生的异常 CallableStatement:主要用来执行pl/sql的一些过程,函数等。 1.写一条恒成立的select语句,无论你输入的条件是什么,总是能讲表中的所有数据输出 select id,last_name from s_emp where '1' ='1'; where 1=1; findByOption(Integer age,String province,String gender){ String sql = select * from s_emp where 1=1; if(age!=null){ sql + "and age < age"; } if(province!=null){ sql + "and province=province"; } if(gender!=null){ sql + "and gender = gender"; } } 4.执行sql语句: execute:返回boolean类型的值,代表是否有结果集返回(如果执行select操作,是有ResultSet的,返回值为true) executeUpdate:返回int类型的值,代表的是,操作执行完成后,受影响的数据库的行计数(针对于insert,update,delete) executeQuery:返回的是ResultSet ResultSet:类似于指针或者游标的东西,里边保存的不是所有的结果,而是指向结果集的正上方。所以如果一旦连接关闭那么ResultSet将取不到值 5.处理结果 如果有结果集,处理结果集 ResultSet next(),每执行一次,向下移动一次,如果有值,返回true,如果没值返回false while(rs.next()){ rs.getType(index/columnName); 如果传的是index,那么索引是从1开始的。 select id,last_name from s_emp; 那么1代表的就是id,依次类推 } 6.关闭资源 先开的后关 D:\oraclexe\app\oracle\product\10.2.0\server\jdbc\lib\ojdbc14.jar linux下启动数据库监听的命令: lsnrctl start; "select id from s_emp where name = '"+name+"'"; table s_user( id , name, age) class User{ } //分别使用Statement对象和PreparedStatement对象实现 public class JDBCTest{ //查找s_user表中所有的数据,并且返回他们的集合 public Collection findAll(){ } //按照名字进行删除 public int deleteUser(String name){ } //将user对象的信息更新到数据库表中 public int updateUser(User user){ } //讲User对象保存到数据库中 public void insertUser(User user){ } } JDBC:本身自动帮我做事务管理的操作 AutoCommit = true; Connection.setAutoCommit(false); 正常: conn.commit(); 异常: conn.rollback(); JDBC批处理: addBatch executeBatch Statement PreparedStatement Statement{ 1.获取连接 getConnection(); 2.创建Statement conn.createStatement(); 3.执行sql语句 String sql .... insert delete update executeUpdate select ----- Result executeQuery 4.如果有结果集处理结果集 5.资源关闭 } Statement: update/delete/insert: stmtExecute(String sql){ 1.获取连接 getConnection(); 2.创建Statement conn.createStatement(); 3.执行sql语句 stmt.execute(sql); 4.资源关闭 } Select: stmtQuery(String sql,ResultHander handler){ 1.获取连接 getConnection(); 2.创建Statement conn.createStatement(); 3.执行sql语句 ResultSet set = executeQuery 4.如果有结果集处理结果集 handler!=null handler.handler(set); 5.资源关闭 } 结果集处理的规则: ResultHandler{ handler(ResultSet rs); } PreparedStatement update/delete/insert: pstmtExecute(String sql,PstmtSetter setter){ 1.获取连接 getConnection(); 2.创建PreparedStatement conn.prepareStatement(sql); if(setter!=null){ setter.setter(pstmt); } 3.执行sql语句 pstmt.execute(sql); 4.资源关闭 } ?设值的标准: PstmtSetter{ setter(PreparedStatement pstmt); } Select: stmtQuery(String sql,PstmtSetter setter,ResultHander handler){ 1.获取连接 getConnection(); 2.创建PreparedStatement conn.prepareStatement(); setter!=null setter.setter(pstmt); 3.执行sql语句 ResultSet set = executeQuery 4.如果有结果集处理结果集 handler!=null handler.handler(set); 5.资源关闭 } 结果集处理的规则: ResultHandler{ handler(ResultSet rs); } 表现层 业务逻辑层 持久层 java中的对象分为: 1.域对象:主要作为信息的载体 2.行为对象:注重操作 Register(User user){ } insert(User user){ String sql = "insert into s_user( user.getId()+user.getName().......)"; } insert(User user){ save(user); } ORM Object Relational Class-Object 表 名字 表名 属性 字段(列) object 记录 User s_User id id name name passwd passwd insert into s_user(id,name,passwd) values(?,?,?); Hibernate:ORM的中间件,或者说是实现了ORM的一个框架,对JDBC做了轻量级的封装。 ORM:使用元数据信息来描述对象和数据库之间的关系,并且能够自动实现java中持久化对象到关系型数据库中表的映射 脏检查:自动对缓存中的数据进行检查,并且选择在合适的时机和数据库之间进行交互,以保持数据的一致性 延迟加载:从数据库中还原对象的时候,不会立即对对象进行初始化,而是等到用到的时候才会进行初始化 Core: POJO hibernate.cfg.xml .hbm.xml Session: 1.轻量级的,创建和销毁不需要消耗很大的资源 2.非线程安全的 3.hibernate的一级缓存 4.介于Connection和Transaction之间的一个对象 5.hibernate中用来做持久化操作的 SessionFactory 1.重量级的,创建和销毁需要消耗很大的资源,不建议频繁创建和销毁 2.线程安全的,一个数据库对应一个Sessionfactory(一般一个应用程序对应一个SessionFactory就够了) 3.是一个很大的缓存,本身维护了一个可配置的二级缓存 4.用来构建Session对象 Configuration 1.启动和配置Hibernate 2.读取hibernate的配置文件和映射文件 3.构建SessionFactory对象 Transaction 1.事务管理对象 Query 1.查询对象,HQL Criteria 1.hibernate提供的更面向对象的一种查询方式。 准备工作: 1.java中的POJO对象存在 2.数据库,表得存在 3.hibernate的配置文件(hibernate.cfg.xml)得存在 4.POJO.hbm.xml文件存在 5.hibernate的jar包以及数据库的驱动包存在 Hibernate的编程: 1.构建Configuration对象读取配置文件 2.读取映射文件 3.构建SessionFactory对象 4.构建Session对象 5.开启事务 6.持久化操作 7.事务的提交(正常提交,不正常回滚) 8.关闭资源 主键增长策略: 1.increment:自动增长 select max(id) from table; 找到最大值之后+1赋给要持久化的对象 2.assigned:指派 hibernate不在自动生成主键值,需要你在插入时自己指明 3.hilo:高低值算法,由数据库表提供高值,程序提供低值 value = hi*(max_lo+1)+lo 4.sequences Cat: cid name color weight age --------------------------- 1.每个人都有一个地址 person{ id name } Address{ country province city street } table: id name country province city street Component:数据库中采用一张表的设计,java中采用两个类的设计 ----------------------------------- Employee: id name salary award amount table id name salary award formula: ---------------------------- 关系模型: 多对一: 订单和客户之间的关系 Order{ id amount customer } Customer{ id name } many-to-one:标签中对于cascade的取值delete,delete-orphan,all-delete-orphan(只用unique属性值不为true不能出现)慎用 cascade:级联属性 none:不做任何级联操作 save-update:对当前对象执行save,update, saveOrupdate,会级联操作和它相关联的对象 delete:在删除当前对象的时候,级联删除和他相关联的对象 all: save-update+delete delete-orphan:解除关联关系时,删除和当前对象失去关联的对象 all-delete-orphan:all+delete-orphan 单向的一对多的关系,在进行关联关系的操作时,会执行不必要的update语句,所以,一般情况下,我们不会做单向一对多的映射。 inverse="true":让其中一方放弃对关联关系的维护 一般在做双向多对一(一对多)关联关系映射的时候,一般会设置让一的一方放弃对关联关系的维护,以减少不必要的更新语句 一对一: 基于外键的一对一 Wife Husband id id name name h_id references Husband(id) unique 基于主键的一对一 Wife Husband id references Husband(id) id name name create table Husband( id number primary key, name varchar2(15) ); create table Wife( id number primary key references husband(id), name varchar2(15) ); 多对多: Teacher Student id id name name 桥表:s_t s_id t_id ------------------------------ 操作持久化对象: Hibernate中对象的三种状态: Transient(瞬态): 1.由new关键字创建 2.没有和Session进行关联的 3.数据库中没有对应的记录存在 4.操作不会影响数据库中的数据 Persistent(持久态): 1.和Session之间有关联 2.在数据库中有对应记录存在,并且有持久化标识 3.对持久对象的更动,会对数据库中的数据产生影响。(自动脏检查机制) Detached(托管状态): 1.和Session失去关联 2.数据库中有对应记录存在 3.对托管对象的更动,在托管期间不会影响数据库,但是将托管状态重新和数据库进行关联的时候会将托管对象重新变为持久态,那么在托管期间发生的更动也会被更新到数据库中 get()/load():从数据库中还原数据 get: 1.先从缓存中进行查找,如果找到就直接返回 2.如果找不到,get()会立即发送sql语句到数据库中查找数据,如果找到就返回,如果找不到返回null; load:(使用延迟加载策略) 1.load()方法默认要加载的对象一定存在,所以很放心的使用代理对象,等到用到的时候从缓存中查找数据,如果找到,就返回,找不到发送sql语句到数据库中查找,如果数据库中没有对应记录存在,抛ObjectNotFoundException Hibernate中的查询: 1.OID检索: get load 2.导航对象图查询: Customer ---- Order之间有对应关系 通过检索到Customer以后,想获取和Customer相关的对象,可以使用 cus.getOrders(); 3.HQL: Query sql: select name from t_cus; hql: select name from hiber.many2one.Customer query.list(); 直接发送一条select语句去表中查找所有的属性 query.iterate(); 先发送一条select语句从表中查找所有的id,然后根据id从缓存中进行查找,找到就返回,找不到再发送sql语句按id从数据库中进行查找,所以可能会产生N+1的问题 Customer order select from customer order where customer.id=order.c_id; 4.QBC(Query By Criteria) Criteria Restrictions Order Projections QBE(Query By Example) 5.sql A B 总额 《 4000 - 100 1900 2100 900 Session默认在遇到以下情况的时候会flush: 1.事务提交的时候 2.某些查询操作执行的时候(不是所有的查询) 3.当应用程序显示的调用session.flush操作的时候 悲观锁: LockMode LockMode.UPGRADE:借助于数据库的 select ... for update; 那么事务一定会等到上一个获取了锁的事务commit之后才执行,如果上一个事务一直不提交,那么它就一直等下去 LockMode.UPGRADE_NOWAIT: select ... for update nowait; nowait就是不等待,一旦在操作过程中发现要操作的数据被加了锁,那么直接抛 ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源 乐观锁: 版本控制(version) 时间戳(timestamp)

62,046

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧