两个表联合分页查询的SQL语句,谢谢!

时间:2021-12-23 13:28:34
学生 A表: pid,name
课程 B表:pid,class,parentclass
学生会上很比较多的课程class(语文、数学),但学生对class又报了parentclass(譬如基础班、考前班),这样,pid和parentclass就会出现一对多。譬如肖明报了语文的基础班,又报了数学的基础班,如果按照parentclass基础班来进行查询学生的话,就会出现两条肖明的数据。
pid      class    parentclass
肖明        语文      基础班
肖明       数学       基础班
 
请教这种情况如何按照parentclass为条件进行分页查询并得出去掉学生重复值的count数。谢谢。

分不多了,谢谢!

17 个解决方案

#1


这和你业务相关,如果需要出class,那出两条完全没问题,如果只要出parentclass,那么可以不抽出class用distinct或者group去重

#2


--去重复计数
SELECT COUNT(DISTINCT pid) FROM B WHERE parentclass = '基础班'
--去重复查询
SELECT DISTINCT pid FROM B WHERE parentclass = '基础班'

#3


引用 1 楼 xdashewan 的回复:
这和你业务相关,如果需要出class,那出两条完全没问题,如果只要出parentclass,那么可以不抽出class用distinct或者group去重


我是要select A表.* from A表 left join B表 on A表.pid=B表.pid where B表.parentclass='基础班',但这样A表会出现重复数据。而且我要求不出现重复数据的情况下分页。

#4


引用 2 楼 Tiger_Zhao 的回复:
--去重复计数
SELECT COUNT(DISTINCT pid) FROM B WHERE parentclass = '基础班'
--去重复查询
SELECT DISTINCT pid FROM B WHERE parentclass = '基础班'


我要求分页!

#5


select A表.* from A表 join(SELECT pid,parentClass B表 where B表.parentclass='基础班' GROUP BY pid,parentClass)T on A表.pid=T.pid 

#6


DECLARE @pageSize int
DECLARE @page int
SET @pageSize = 100
SET @page = 2

    SELECT pid
      FROM (
            SELECT DISTINCT pid,
                   ROW_NUMBER() OVER (ORDER BY GetDate()) rn
              FROM B
             WHERE parentclass = '基础班'
           ) t
     WHERE rn BETWEEN (@page-1)*@pageSize+1 AND @page*@pageSize
  ORDER BY rn

#7


引用 6 楼 Tiger_Zhao 的回复:
DECLARE @pageSize int
DECLARE @page int
SET @pageSize = 100
SET @page = 2

    SELECT pid
      FROM (
            SELECT DISTINCT pid,
                   ROW_NUMBER() OVER (ORDER BY GetDate()) rn
              FROM B
             WHERE parentclass = '基础班'
           ) t
     WHERE rn BETWEEN (@page-1)*@pageSize+1 AND @page*@pageSize
  ORDER BY rn


你好,我的是两个表哦?

#8


分页结果再和A关联啊!
反正有了不重负的pid,输出字段自己按需要调整。

#9


引用 8 楼 Tiger_Zhao 的回复:
分页结果再和A关联啊!
反正有了不重负的pid,输出字段自己按需要调整。


不好意思,我的是sql2000。
我琢磨了第一页的数据调用可以这样:
[code]select top 10 a.pid,a.name from  A表 a LEFT JOIN B表 b ON a.pid=b.pid where b.parentclass='基础班' group by a.pid order by a.pid desc[/code]
但后面的页和count就不知道怎么写了

#10



select top 10 a.pid,a.name from  A表 a LEFT JOIN B表 b ON a.pid=b.pid where b.parentclass='基础班' group by a.pid,a.name  order by a.pid desc

#11


各位看我解决得对不对?

第一页:



select top 10 a.pid,a.name from A表 a left join B表 b ON a.pid=b.pid where b.parentclass='基础班' group by a.pid,a.name order by a.pid desc

第二页:

select top 10 a.pid,a.name from A表 a left join B表 b ON a.pid=b.pid where b.parentclass='基础班' and b.pid >(select min(pid)  from (select top 10 pid  from  B表  where parentclass='基础班' group by pid  order by pid desc) as tmp)  group by a.pid,a.name order by a.pid desc


cout总数是这样吗?

select distinct count(*) from B表 where parentclass=‘基础班’


sql2000数据库,求指点!!如能优化更加感激不尽!

#12


第一页 没问题,前台需要记下本页最大pid
第二页 加条件
select top 10 a.pid,a.name 
from A表 a 
left join B表 b ON a.pid=b.pid 
where b.parentclass='基础班' 
and a.pid > @上页最大pid
group by a.pid,a.name 
order by a.pid desc


#13


去重字段加个MAX就好 了,count(*)就是求总数,只有一个结果不需要distinct 

#14


引用 13 楼 jph1122 的回复:
去重字段加个MAX就好 了,count(*)就是求总数,只有一个结果不需要distinct 


因为是两个表left join 所有有重复的行的。

#15


引用 12 楼 Tiger_Zhao 的回复:
第一页 没问题,前台需要记下本页最大pid
第二页 加条件
select top 10 a.pid,a.name 
from A表 a 
left join B表 b ON a.pid=b.pid 
where b.parentclass='基础班' 
and a.pid > @上页最大pid
group by a.pid,a.name 
order by a.pid desc


这个确实是可以节省一次对max 或者min pid的查询,但不排除有从第一页直接点击到第五页的。hoho。。

#16


能点第五页,那么你最开始取过总页数了。
不如改成这样:
1)把有序的pid插入有自增行号的临时表
2)从临时表中统计每也的最小、最大pid返回

所有的分页查询都可以统一成下面这样
select top 10 a.pid,a.name --top 10 其实不需要了
from A表 a 
left join B表 b ON a.pid=b.pid 
where b.parentclass='基础班' 
and a.pid BETWEEN @页内最小pid AND @页内最大pid
group by a.pid,a.name 
order by a.pid desc

#17


引用 14 楼 kokoliu 的回复:
Quote: 引用 13 楼 jph1122 的回复:

去重字段加个MAX就好 了,count(*)就是求总数,只有一个结果不需要distinct 


因为是两个表left join 所有有重复的行的。

select #A.PID,#A.NAME,PARENTCLASS,MAX(CLASS) CLASS from #A JOIN #B on #A.PID=#B.PID
GROUP BY #A.PID,#A.NAME,PARENTCLASS

#1


这和你业务相关,如果需要出class,那出两条完全没问题,如果只要出parentclass,那么可以不抽出class用distinct或者group去重

#2


--去重复计数
SELECT COUNT(DISTINCT pid) FROM B WHERE parentclass = '基础班'
--去重复查询
SELECT DISTINCT pid FROM B WHERE parentclass = '基础班'

#3


引用 1 楼 xdashewan 的回复:
这和你业务相关,如果需要出class,那出两条完全没问题,如果只要出parentclass,那么可以不抽出class用distinct或者group去重


我是要select A表.* from A表 left join B表 on A表.pid=B表.pid where B表.parentclass='基础班',但这样A表会出现重复数据。而且我要求不出现重复数据的情况下分页。

#4


引用 2 楼 Tiger_Zhao 的回复:
--去重复计数
SELECT COUNT(DISTINCT pid) FROM B WHERE parentclass = '基础班'
--去重复查询
SELECT DISTINCT pid FROM B WHERE parentclass = '基础班'


我要求分页!

#5


select A表.* from A表 join(SELECT pid,parentClass B表 where B表.parentclass='基础班' GROUP BY pid,parentClass)T on A表.pid=T.pid 

#6


DECLARE @pageSize int
DECLARE @page int
SET @pageSize = 100
SET @page = 2

    SELECT pid
      FROM (
            SELECT DISTINCT pid,
                   ROW_NUMBER() OVER (ORDER BY GetDate()) rn
              FROM B
             WHERE parentclass = '基础班'
           ) t
     WHERE rn BETWEEN (@page-1)*@pageSize+1 AND @page*@pageSize
  ORDER BY rn

#7


引用 6 楼 Tiger_Zhao 的回复:
DECLARE @pageSize int
DECLARE @page int
SET @pageSize = 100
SET @page = 2

    SELECT pid
      FROM (
            SELECT DISTINCT pid,
                   ROW_NUMBER() OVER (ORDER BY GetDate()) rn
              FROM B
             WHERE parentclass = '基础班'
           ) t
     WHERE rn BETWEEN (@page-1)*@pageSize+1 AND @page*@pageSize
  ORDER BY rn


你好,我的是两个表哦?

#8


分页结果再和A关联啊!
反正有了不重负的pid,输出字段自己按需要调整。

#9


引用 8 楼 Tiger_Zhao 的回复:
分页结果再和A关联啊!
反正有了不重负的pid,输出字段自己按需要调整。


不好意思,我的是sql2000。
我琢磨了第一页的数据调用可以这样:
[code]select top 10 a.pid,a.name from  A表 a LEFT JOIN B表 b ON a.pid=b.pid where b.parentclass='基础班' group by a.pid order by a.pid desc[/code]
但后面的页和count就不知道怎么写了

#10



select top 10 a.pid,a.name from  A表 a LEFT JOIN B表 b ON a.pid=b.pid where b.parentclass='基础班' group by a.pid,a.name  order by a.pid desc

#11


各位看我解决得对不对?

第一页:



select top 10 a.pid,a.name from A表 a left join B表 b ON a.pid=b.pid where b.parentclass='基础班' group by a.pid,a.name order by a.pid desc

第二页:

select top 10 a.pid,a.name from A表 a left join B表 b ON a.pid=b.pid where b.parentclass='基础班' and b.pid >(select min(pid)  from (select top 10 pid  from  B表  where parentclass='基础班' group by pid  order by pid desc) as tmp)  group by a.pid,a.name order by a.pid desc


cout总数是这样吗?

select distinct count(*) from B表 where parentclass=‘基础班’


sql2000数据库,求指点!!如能优化更加感激不尽!

#12


第一页 没问题,前台需要记下本页最大pid
第二页 加条件
select top 10 a.pid,a.name 
from A表 a 
left join B表 b ON a.pid=b.pid 
where b.parentclass='基础班' 
and a.pid > @上页最大pid
group by a.pid,a.name 
order by a.pid desc


#13


去重字段加个MAX就好 了,count(*)就是求总数,只有一个结果不需要distinct 

#14


引用 13 楼 jph1122 的回复:
去重字段加个MAX就好 了,count(*)就是求总数,只有一个结果不需要distinct 


因为是两个表left join 所有有重复的行的。

#15


引用 12 楼 Tiger_Zhao 的回复:
第一页 没问题,前台需要记下本页最大pid
第二页 加条件
select top 10 a.pid,a.name 
from A表 a 
left join B表 b ON a.pid=b.pid 
where b.parentclass='基础班' 
and a.pid > @上页最大pid
group by a.pid,a.name 
order by a.pid desc


这个确实是可以节省一次对max 或者min pid的查询,但不排除有从第一页直接点击到第五页的。hoho。。

#16


能点第五页,那么你最开始取过总页数了。
不如改成这样:
1)把有序的pid插入有自增行号的临时表
2)从临时表中统计每也的最小、最大pid返回

所有的分页查询都可以统一成下面这样
select top 10 a.pid,a.name --top 10 其实不需要了
from A表 a 
left join B表 b ON a.pid=b.pid 
where b.parentclass='基础班' 
and a.pid BETWEEN @页内最小pid AND @页内最大pid
group by a.pid,a.name 
order by a.pid desc

#17


引用 14 楼 kokoliu 的回复:
Quote: 引用 13 楼 jph1122 的回复:

去重字段加个MAX就好 了,count(*)就是求总数,只有一个结果不需要distinct 


因为是两个表left join 所有有重复的行的。

select #A.PID,#A.NAME,PARENTCLASS,MAX(CLASS) CLASS from #A JOIN #B on #A.PID=#B.PID
GROUP BY #A.PID,#A.NAME,PARENTCLASS