还记得年前的一个SQL问题,当时对SQL刚接触,因此绕开了它。用了别的办法。昨天看SQL突然想起了这个问题。百思不得其解,然后去SQL Server技术交流群,也请教了,大神高文佳,何志勇提示我因为先分组然后再链接。但由于小弟技术是在是太菜,因此没能弄出我想要的结果来。后来由于太晚的原因或者是问题太简单(当然大神们实在是很热情),大神们都睡觉了。今天还是在纠结这个问题的解决方法。

先给出测试用的初始化表和数据:

CREATE TABLE [dbo].tab_1(
[Id] [int] NOT NULL,
[SkillId] [int] NOT NULL
) ON [PRIMARY] CREATE TABLE [dbo].tab_2(
[Id] [int] NOT NULL,
[SkillId] [int] NOT NULL
) ON [PRIMARY] GO insert into tab_1 values(1,1)
insert into tab_1 values(1,2)
insert into tab_1 values(2,1)
insert into tab_1 values(2,3)
insert into tab_1 values(2,6) insert into tab_2 values(5,1)
insert into tab_2 values(5,2)
insert into tab_2 values(5,4)
insert into tab_2 values(7,1)
insert into tab_2 values(7,3)
insert into tab_2 values(7,6)

查询表数据如下:

 tab_1

tab_2

问题1:现在的问题是想查出这部分数据(语言表达能力不好,我就直接给图了^_^):

也就是每组根据Id分组后,取tab_1和tab_2有完全相同的SkillId分组项。

开始就一直思考如何用分组、联接来实现。后来发现有各种不同的问题(当然是我的问题),最终换了思路,将每个表根据主键分组(为了测试方便我没有设主键),然后使用合并列的方法来曲线实现了一下:

with cte1 as(
select Id, stuff((select ','+ CONVERT(varchar,SkillId) from tab_1 t where t.Id=t1.Id for xml path('')),1,1,'') as Skills from tab_1 t1
group by Id
),
cte2 as(
select Id, stuff((select ','+ CONVERT(varchar,SkillId) from tab_2 tt where tt.Id=tt1.Id for xml path('')),1,1,'') as Skills from tab_2 tt1
group by Id
)select * from cte1 join cte2 on cte1.Skills=cte2.Skills

但是我想这个方法是不好的。因为如果此时我给表tab_1添加一列:

insert into tab_1 values(2,5)

问题2:我想取出这部分数据:

也就是每组根据Id分组后,判断tab_1的某个分组的SkillId是否完整包含tab_2的某个分组的SkillId。这个时候再用分组合并的办法就不管用了。

当然呢,大神们很快就发现了使用charindex来实现:

with cte1 as(
select Id, stuff((select ','+ CONVERT(varchar,SkillId) from tab_1 t where t.Id=t1.Id for xml path('')),1,1,'') as Skills from tab_1 t1
group by Id
),
cte2 as(
select Id, stuff((select ','+ CONVERT(varchar,SkillId) from tab_2 tt where tt.Id=tt1.Id for xml path('')),1,1,'') as Skills from tab_2 tt1
group by Id
)select * from cte1 join cte2 on CHARINDEX(cte2.Skills,cte1.Skills)=1

以上只是用到了SQL Server的for xml path()列转行,stuff()字符串函数截取以及charindex()字符串函数来比较字符串。

另外根据@小飞虾、@小不正经提供的思路:

1.对2各表分别根据主键字段组内排序计算出每组的总数

2.对结果1的2个表根据关联字段SkillId进行表联接,并根据1中2个表的主键字段进行组内排序,计算出此结果集的每组的总数

3.将2得出的结果集进行条件运算。如果问题1的要求则用等号计算;如果是问题2的要求则用>=计算。T-SQL如下:

with cte1 as(
select id,SkillId,count(1) over (partition by Id) as count1 from tab_1
),cte2 as(
select id,SkillId,count(1) over (partition by Id) as count2 from tab_2
),cte3 as(
select cte1.Id,cte1.Skillid,count1,cte2.Id as Id2,cte2.SkillId as SkillId2,cte2.count2,
COUNT(1) over (partition by cte1.Id,cte2.Id) as count3
from cte1 full join cte2
on cte1.SkillId=cte2.SkillId
)select Id,SkillId,Id2,SkillId2 from cte3
where count1 >=count2 and count3 >=count2

那么有什么更多的好的办法没有呢?肯定是有的对吧。请各抒己见,在此肯求大伙儿热心指教。不胜感激!

一个1年前的T-SQL问题的更多相关文章

  1. 如果一条SQL语句太长,我们可以通过回车键来创建一个新行来编写SQL语句,SQL语句的命令结束符为分号(;)。

    1.如果一条SQL语句太长,我们可以通过回车键来创建一个新行来编写SQL语句,SQL语句的命令结束符为分号(;). 2.select查询的多个字段之间要用逗号“,”分割,如果查询涉及多个表,那多个表之 ...

  2. 为什么我要使用一个20年前的IBM老键盘

    为什么我要使用一个20年前的IBM老键盘 发表在 心得体会 | 3条评论 几天前,我在网上发了一张图片,想炫耀了一下我的新MacBook Pro笔记本强悍的多屏功能.没人感兴趣.但图上的那个老键盘却得 ...

  3. 一个看似很简单的SQL却难倒了很多人

    一个选课表,有学生id,课程id,老师id,要求选出同时选了语文和数学的学生 USE [tempschool] GO /****** 对象: Table [dbo].[SelectC] 脚本日期: 0 ...

  4. 通过一个小问题来学习SQL关联查询

    原话题: 是关于一个left join的,没有技术难度,但不想清楚不一定能回答出正确答案来: TabA表有三个字段Id,Col1,Col2 且里面有一条数据1,1,2 TabB表有两个字段Id,Col ...

  5. 一个简单的ORM制作(SQL帮助类)

    一个简单的ORM制作大概需要以下几个类: SQL执行类 CURD操作类 其他酱油类 先从SQL执行类说起,可能会涉及数据库的迁移等问题,所以需要定义一个接口以方便迁移到其他数据库, 事务没提供命名,若 ...

  6. 一个令人困惑的低效SQL

    整理之前的优化案例,觉得下面这个应该是开发很难发现也会很困惑的一个低效SQL. 看下面这个SQL.你看到这个SQL会不会感觉很正常.其实我刚看到也觉得正常得不得了.但是测试后它确实效率很低.selec ...

  7. 一个能够编写、运行SQL查询并可视化结果的Web应用:SqlPad

    SqlPad 是一个能够用于编写.运行 SQL 查询并可视化结果的 Web 应用.支持 PostgreSQL.MySQL 和 SQL Server.SqlPad 目前仅适合单个团队在内网中使用,它直接 ...

  8. 一个关于考勤统计的sql研究

    在这里,我们要做一个简单的员工考勤记录查询系统的后台数据库.业务需求如下所示:      1.统计每天来的最早.来的最晚.走的最早.走得最晚的人的姓名           1.1 统计每天来得最早的人 ...

  9. mybatis前台传来一个String,后后台执行sql变成了true

    实际上参数传来的是一个字符串 3 ,不知道为什么会变成true 最后当然是查不到信息了.. 我在mapper映射文件里面使用了动态的where查询,我觉得跟这个关系不太大, 现在不知道怎么办,希望有思 ...

随机推荐

  1. 你的C#代码是怎么跑起来的(一)

    写了那么多C#代码,大家有没有想过自己写的代码编译后的可执行文件内部是什么样子,是怎样在系统上运行的? 编译成exe,然后双击exe文件运行,这中间到底发生了些什么呢,这篇先来剖析下exe内部的样子: ...

  2. 关于json 与 Request Header 的Content-Type 一些关系。

    由于最近遇到关于,ashx文件ajax解析参数的问题.查询网上很多资料后,已经解决. 鉴于网上已经足够多的,关于这个问题的文章.大部分内容来自互联网,我这里只是做一些整理和记录.特此说明并非原创. C ...

  3. Daily English

  4. 16.C#初见Lambda表达式及表达式树(九章9.1-9.3)

    在说明Lambda相关知识前,我们需要了解Lambda表达式常用于LINQ,那么我们来聊下LINQ. LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态.这些操作表示了各种关于数据的逻辑: ...

  5. 08.C# System.Nulable<T>和空引用操作符(四章4.2-4.4)

    看了这3小节,发现作者讲得太详细了,把一个都在正常使用的用法说得太神密了,搞得不知是自己不懂作者的苦心,还是作者用意为之,这里给大家都简单讲下吧,太深的真心讲不下去. 1.可空类型的核心部分是Syst ...

  6. Nginx下Redmine配置

    安装redmine依赖的所有ruby包 cd .. gem install bundler #注意是在网站根目录下执行 bundle install --without development tes ...

  7. java和linux的编码

    最近要使用中科院计算所的关键词工具NLPIR,用java调用,在windows下测试后放到linux下跑,就发现会有乱码. windows下默认是GBK,linux下是utf-8,因此在意料之中(尽管 ...

  8. 深入理解web项目的配置文件

    1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧急着,容创建一个Servl ...

  9. iOS开发小技巧--利用苹果官方API播放视频(方法已经过时,了解一下)

  10. hdu2807 矩阵乘法+floyd

    网上有优化的方法 就是乘上一个一维的矩阵:现在还没有想通.想通了不上代码: 我用的就是普通的矩阵,压着时间过:只是多了一个判断条件,不加这个条件就超时: #include<stdio.h> ...