一个1年前的T-SQL问题
还记得年前的一个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问题的更多相关文章
- 如果一条SQL语句太长,我们可以通过回车键来创建一个新行来编写SQL语句,SQL语句的命令结束符为分号(;)。
1.如果一条SQL语句太长,我们可以通过回车键来创建一个新行来编写SQL语句,SQL语句的命令结束符为分号(;). 2.select查询的多个字段之间要用逗号“,”分割,如果查询涉及多个表,那多个表之 ...
- 为什么我要使用一个20年前的IBM老键盘
为什么我要使用一个20年前的IBM老键盘 发表在 心得体会 | 3条评论 几天前,我在网上发了一张图片,想炫耀了一下我的新MacBook Pro笔记本强悍的多屏功能.没人感兴趣.但图上的那个老键盘却得 ...
- 一个看似很简单的SQL却难倒了很多人
一个选课表,有学生id,课程id,老师id,要求选出同时选了语文和数学的学生 USE [tempschool] GO /****** 对象: Table [dbo].[SelectC] 脚本日期: 0 ...
- 通过一个小问题来学习SQL关联查询
原话题: 是关于一个left join的,没有技术难度,但不想清楚不一定能回答出正确答案来: TabA表有三个字段Id,Col1,Col2 且里面有一条数据1,1,2 TabB表有两个字段Id,Col ...
- 一个简单的ORM制作(SQL帮助类)
一个简单的ORM制作大概需要以下几个类: SQL执行类 CURD操作类 其他酱油类 先从SQL执行类说起,可能会涉及数据库的迁移等问题,所以需要定义一个接口以方便迁移到其他数据库, 事务没提供命名,若 ...
- 一个令人困惑的低效SQL
整理之前的优化案例,觉得下面这个应该是开发很难发现也会很困惑的一个低效SQL. 看下面这个SQL.你看到这个SQL会不会感觉很正常.其实我刚看到也觉得正常得不得了.但是测试后它确实效率很低.selec ...
- 一个能够编写、运行SQL查询并可视化结果的Web应用:SqlPad
SqlPad 是一个能够用于编写.运行 SQL 查询并可视化结果的 Web 应用.支持 PostgreSQL.MySQL 和 SQL Server.SqlPad 目前仅适合单个团队在内网中使用,它直接 ...
- 一个关于考勤统计的sql研究
在这里,我们要做一个简单的员工考勤记录查询系统的后台数据库.业务需求如下所示: 1.统计每天来的最早.来的最晚.走的最早.走得最晚的人的姓名 1.1 统计每天来得最早的人 ...
- mybatis前台传来一个String,后后台执行sql变成了true
实际上参数传来的是一个字符串 3 ,不知道为什么会变成true 最后当然是查不到信息了.. 我在mapper映射文件里面使用了动态的where查询,我觉得跟这个关系不太大, 现在不知道怎么办,希望有思 ...
随机推荐
- 如何在WPF中引用Windows.System.Forms.Integration
转自 http://www.cnblogs.com/sinozhang1988/archive/2012/11/28/2792804.html “未找到程序集 WindowsFormsIntegrat ...
- WP & Win10开发:实现ListView下拉加载的两种方法
1.通过ListView控件的ContainerContentChanging方法.该方法在列表项被实例化时触发,在列表项最后一个项目实例化的时候触发刷新数据逻辑就可以实现下拉加载了. 代码如下:// ...
- El Capitan 中 SIP 介绍
http://havee.me/mac/2015-10/system-integrity-protection-on-el-capitan.html 这两天大家纷纷将 OS X 系统升级到了 El C ...
- 云计算之路-阿里云上:2014年6月12日16:14遭遇SLB故障
这是今天遇到的第3次故障,故障是首先被园友发现的,访问园子出现来自SLB的错误提示:400 Bad Request - Powered by Tengine. 查看Windows性能监视器发现,在故障 ...
- Bootstrap系列 -- 35. 按钮的向下向上三角形
按钮的向下三角形,我们是通过在<button>标签中添加一个“<span>”标签元素,并且命名为“caret”. <div class="btn-group d ...
- c#简单自定义异常处理日志辅助类
简单写了一个错误日志记录辅助类,记录在此. Loghelper类 using System; using System.Collections.Generic; using System.IO; us ...
- Moqui学习之代码分析mantle priceServices.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- This software is in the pub ...
- 关于Jquery 操作Cookie 取值错误
使用JQuery操作cookie时 发生取的值不正确的问题: 结果发现cookie有四个不同的属性: 名称,内容,域,路径 $.cookie('the_cookie'); // 读取 cookie $ ...
- Shell编程中Shift的用法
Shell编程中Shift的用法 位置参数可以用shift命令左移.比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1.$2.$3丢弃,$0不移动.不带参数的shif ...
- 【Matplotlib】 刻度设置(2)
Tick locating and formatting 该模块包括许多类以支持完整的刻度位置和格式的配置.尽管 locators 与主刻度或小刻度没有关系,他们经由 Axis 类使用来支持主刻度和小 ...