还记得年前的一个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. (译)JavaScript内存泄露

    译者前言 原文地址:Memory leaks 最近简单了解了下JavaScript的闭包和垃圾回收机制(GC),这中间也不得不接触内存泄露这个概念.然后不小心找到了这篇文章,看下来后理解了不少东西,于 ...

  2. Asp.Net MVC 合并js或css请求

    Step1:BundleConfig中注册 bundles.Add(new ScriptBundle("~/isValid").Include(  "~/Scripts/ ...

  3. [软件测试]Linux环境中简单清爽的Google Test (GTest)测试环境搭建(初级使用)

    本文将介绍单元测试工具google test(GTEST)在linux操作系统中测试环境的搭建方法.本文属于google test使用的基础教程.在linux中使用google test之前,需要对如 ...

  4. Unity3D 文字滚动跑马灯效果

    需求 在日常游戏中,文字滚动效果是比较常用的.例如日常游戏顶部的新闻公告,聊天系统的文字滚动,都属于这个范围. 思路 由于使用的地方比较广泛,所以希望能够尽量独立的游戏之外,能够做到随处使用的功能.N ...

  5. Jquery.validate.js表单验证插件的使用

    作为一个网站web开发人员,以前居然不知道还有表单验证这样好呀的插件,还在一行行写表单验证,真是后悔没能早点知道他们的存在. 最近公司不忙,自己学习一些东西的时候,发现了validation的一个实例 ...

  6. QRadioButton分组且无边框的简单实现

    最近在用QT+VS2008做一个项目,涉及到一个综合测评表,说白了有点像问卷调查——很多题目每题若干个选项. 初始时打算用下拉框,每个框中填入所有选项,但后来一琢磨这种方式不够直观与人性化,增添了一步 ...

  7. Intelli IDEA 14.04开发版+注册码

    Idea,一款比较出色的IDE开发工具,懂她的人,自然懂得. 本版本-14.04+注册码 注册界面  注册码:               Name:happy                KEY: ...

  8. linux查看cpu、内存、版本信息

    1.  查看物理CPU的个数#cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc –l 2.   查看逻辑CPU的个数#cat ...

  9. 结对子作业 四则运算 V2.0

    import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import ja ...

  10. windows Server2008R2 每隔一段时间自动关机解决办法

    情况描述: “我的电脑-->右键属性”中显示“已激活”,而“管理工具”中显示未激活.系统中有进程wlms.exe. 网上找了下解决方式: 1.提权工具:PSTOOLS(下载地址:http://m ...