SQL行转列应用的动态实现方式
<p>概述:
</p>
<p>
SQL行转列的需求,在项目中还是经常可见的,尤其报表类的应用,更是非常广泛!上期我们讲了SQL行转列的静态实现方式,本期搞一下行转列的动态实现方案,解决方案并不唯一,这里采用存储过程的实现方式!
</p>
<center>
<img title="SQL行转列应用的动态实现方式" alt="SQL行转列应用的动态实现方式" src="https://zhuji.jb51.net/uploads/img/202305/4a1d082ae94be54fdfa45712c8233ee1.jpg">
</center>
<h3>
接下来我们详细讲解下SQL动态行转列的实现步骤:
</h3>
<h3>
创建模拟数据:
</h3>
<p>
这里还是老套路,IT编程人入门的经典学生选课表系列,学生表、课程表、成绩表!就拿这套耳熟能详的表结构进行讲解!
</p>
<center>
<img title="SQL行转列应用的动态实现方式" alt="SQL行转列应用的动态实现方式" src="https://zhuji.jb51.net/uploads/img/202305/e8fbc96a2413bd4a4ce8d3e9f49e7fcc.jpg">
</center>
<center>
<img title="SQL行转列应用的动态实现方式" alt="SQL行转列应用的动态实现方式" src="https://zhuji.jb51.net/uploads/img/202305/5559b6d06bce977de877799e431ed0a3.jpg">
</center>
<p>
插入模拟的数据,用于动态行转案例的使用!
</p>
<center>
<img title="SQL行转列应用的动态实现方式" alt="SQL行转列应用的动态实现方式" src="https://zhuji.jb51.net/uploads/img/202305/f6335b7f210265f3a6b985a6b13fa815.jpg">
</center>
<p>
先写好静态行转列SQL:
</p>
<p>
这一步相对还是比较重要,毕竟我们要在一个静态的行转列基础之上,构建动态的行转列应用,课程数据会有动态变化,学生也会选择新开的课程,这样静态模式势必不会有效,但参照静态模板,去开发动态的模式,则更加有参照性!
</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">SELECT</span><span> S.SID,S.sname, </span></span>
</li>
<li>
<span><span class="keyword">MAX</span><span>(</span><span class="func">case</span><span> c.cname </span><span class="keyword">when</span><span> </span><span class="string">'数学'</span><span> </span><span class="keyword">then</span><span> sc.score </span><span class="keyword">else</span><span> 0 </span><span class="keyword">end</span><span>) </span><span class="keyword">as</span><span> 数学, </span></span>
</li>
<li class="alt">
<span><span class="keyword">MAX</span><span>(</span><span class="func">case</span><span> c.cname </span><span class="keyword">when</span><span> </span><span class="string">'语文'</span><span> </span><span class="keyword">then</span><span> sc.score </span><span class="keyword">else</span><span> 0 </span><span class="keyword">end</span><span>) </span><span class="keyword">as</span><span> 语文, </span></span>
</li>
<li>
<span><span class="keyword">MAX</span><span>(</span><span class="func">case</span><span> c.cname </span><span class="keyword">when</span><span> </span><span class="string">'英语'</span><span> </span><span class="keyword">then</span><span> sc.score </span><span class="keyword">else</span><span> 0 </span><span class="keyword">end</span><span>) </span><span class="keyword">as</span><span> 英语 </span></span>
</li>
<li class="alt">
<span><span class="keyword">FROM</span><span> Student </span><span class="keyword">as</span><span> S </span></span>
</li>
<li>
<span><span class="func">LEFT</span><span> </span><span class="op">JOIN</span><span> SC </span><span class="keyword">AS</span><span> SC </span><span class="keyword">ON</span><span> S.sid = SC.SID </span></span>
</li>
<li class="alt">
<span><span class="func">LEFT</span><span> </span><span class="op">JOIN</span><span> Course </span><span class="keyword">AS</span><span> C </span><span class="keyword">ON</span><span> C.cid = SC.CID </span></span>
</li>
<li>
<span><span class="keyword">GROUP</span><span> </span><span class="keyword">BY</span><span> S.sid,S.sname </span></span>
</li>
</ol>
<center>
<img title="SQL行转列应用的动态实现方式" alt="SQL行转列应用的动态实现方式" src="https://zhuji.jb51.net/uploads/img/202305/e1e7a17a2c683456461fda831c8d0ce1.jpg">
</center>
<p>
通过测试,数据效果没有问题,正是我们期待的样子!
</p>
<h3>
编写动态脚本:
</h3>
<p>
动态行转列无疑需要使用SQL编程的技术,动态的递归课程名称,这样才可以一劳永逸的解决问题!
</p>
<p>
先编写动态的SQL脚本:
</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">DECLARE</span><span> @SQL </span><span class="keyword">VARCHAR</span><span>(</span><span class="keyword">MAX</span><span>) </span></span>
</li>
<li>
<span></span>
</li>
<li class="alt">
<span><span class="keyword">SELECT</span><span> @SQL = </span><span class="string">' SELECT S.SID,S.SNAME '</span><span> </span></span>
</li>
<li>
<span><span class="keyword">SELECT</span><span> @SQL = @SQL + </span><span class="string">' , ISNULL(MAX(CASE c.cname WHEN '</span><span class="string">''</span><span>+cname+</span><span class="string">''</span><span class="string">' THEN sc.score END ),0) AS '</span><span class="string">''</span><span>+c.cname+</span><span class="string">''</span><span class="string">' '</span><span> </span></span>
</li>
<li class="alt">
<span><span class="keyword">FROM</span><span> Course </span><span class="keyword">AS</span><span> C </span></span>
</li>
<li>
<span></span>
</li>
<li class="alt">
<span>print @sql </span>
</li>
<li>
<span></span>
</li>
<li class="alt">
<span><span class="keyword">SELECT</span><span> @SQL = @SQL + ' </span><span class="keyword">FROM</span><span> Student </span><span class="keyword">as</span><span> S </span></span>
</li>
<li>
<span><span class="func">LEFT</span><span> </span><span class="op">JOIN</span><span> SC </span><span class="keyword">AS</span><span> SC </span><span class="keyword">ON</span><span> S.sid = SC.SID </span></span>
</li>
<li class="alt">
<span><span class="func">LEFT</span><span> </span><span class="op">JOIN</span><span> Course </span><span class="keyword">AS</span><span> C </span><span class="keyword">ON</span><span> C.cid = SC.CID </span></span>
</li>
<li>
<span><span class="keyword">GROUP</span><span> </span><span class="keyword">BY</span><span> S.sid,S.sname' </span></span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span>print @sql </span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span><span class="keyword">EXEC</span><span> (@SQL) </span></span>
</li>
</ol>
<p>
测试结果与静态SQL完全一致,看来问题已经解决,接下来就是优化的问题了!
</p>
<center>
<img title="SQL行转列应用的动态实现方式" alt="SQL行转列应用的动态实现方式" src="https://zhuji.jb51.net/uploads/img/202305/83fbb3e8c0f111a5b8f3e404d933096d.jpg">
</center>
<p>
将上述的动态脚本封装成存储过程,第一可以尽量地提升查询效率,第二方便代码段的调用!
</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">CREATE</span><span> PROC StudentScore_Proc </span></span>
</li>
<li>
<span><span class="keyword">AS</span><span> </span></span>
</li>
<li class="alt">
<span><span class="keyword">BEGIN</span><span> </span></span>
</li>
<li>
<span></span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span><span class="keyword">DECLARE</span><span> @SQL NVARCHAR(</span><span class="keyword">MAX</span><span>) </span></span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span><span class="keyword">SELECT</span><span> @SQL = N</span><span class="string">' SELECT S.SID,S.SNAME '</span><span> </span></span>
</li>
<li class="alt">
<span><span class="keyword">SELECT</span><span> @SQL = @SQL + N</span><span class="string">' , ISNULL(MAX(CASE c.cname WHEN '</span><span class="string">''</span><span>+cname+</span><span class="string">''</span><span class="string">' THEN sc.score END ),0) AS '</span><span class="string">''</span><span>+c.cname+</span><span class="string">''</span><span class="string">' '</span><span> </span></span>
</li>
<li>
<span><span class="keyword">FROM</span><span> Course </span><span class="keyword">AS</span><span> C </span></span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span></span>
</li>
<li class="alt">
<span><span class="keyword">SELECT</span><span> @SQL = @SQL + N' </span><span class="keyword">FROM</span><span> Student </span><span class="keyword">as</span><span> S </span></span>
</li>
<li>
<span><span class="func">LEFT</span><span> </span><span class="op">JOIN</span><span> SC </span><span class="keyword">AS</span><span> SC </span><span class="keyword">ON</span><span> S.sid = SC.SID </span></span>
</li>
<li class="alt">
<span><span class="func">LEFT</span><span> </span><span class="op">JOIN</span><span> Course </span><span class="keyword">AS</span><span> C </span><span class="keyword">ON</span><span> C.cid = SC.CID </span></span>
</li>
<li>
<span><span class="keyword">GROUP</span><span> </span><span class="keyword">BY</span><span> S.sid,S.sname' </span></span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span>print @sql </span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span><span class="keyword">EXECUTE</span><span> sp_executesql </span></span>
</li>
<li class="alt">
<span>@STMT = @SQL </span>
</li>
<li>
<span></span>
</li>
<li class="alt">
<span><span class="keyword">END</span><span> </span></span>
</li>
<li>
<span></span>
</li>
<li class="alt">
<span><span class="keyword">EXEC</span><span> dbo.StudentScore_Proc </span></span>
</li>
</ol>
<p>
封装完存储过程,我们再执行一下,看看结果!果然没有任何问题,与预期完全一致!
</p>
<center>
<img title="SQL行转列应用的动态实现方式" alt="SQL行转列应用的动态实现方式" src="https://zhuji.jb51.net/uploads/img/202305/2711a71516280952ce6ec2ec37f579b6.jpg">
</center>
<p>
这时候我们更改一下数据,课程表中新增物理、化学两门课程,诺克萨斯之手分别选择了两门课程,盖伦仅仅选择了化学,武器大师逃学,俩门课都没有选择。
</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">INSERT</span><span> </span><span class="keyword">INTO</span><span> Course </span><span class="keyword">SELECT</span><span> 4,</span><span class="string">'物理'</span><span> </span></span>
</li>
<li>
<span><span class="keyword">INSERT</span><span> </span><span class="keyword">INTO</span><span> Course </span><span class="keyword">SELECT</span><span> 5,</span><span class="string">'化学'</span><span> </span></span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span><span class="keyword">INSERT</span><span> </span><span class="keyword">INTO</span><span> SC </span><span class="keyword">SELECT</span><span> 1,4,99 </span></span>
</li>
<li class="alt">
<span><span class="keyword">INSERT</span><span> </span><span class="keyword">INTO</span><span> SC </span><span class="keyword">SELECT</span><span> 1,5,88 </span></span>
</li>
<li>
<span><span class="keyword">INSERT</span><span> </span><span class="keyword">INTO</span><span> SC </span><span class="keyword">SELECT</span><span> 2,5,77 </span></span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span><span class="keyword">EXEC</span><span> dbo.StudentScore_Proc </span></span>
</li>
</ol>
<p>
数据改变之后,我们继续测试一下,再次执行我们编写好的存储过程,结果非常完美,随着数据的变化,查询的结果集也是对应的变化,非常NICE,大功告成了!
</p>
<center>
<img title="SQL行转列应用的动态实现方式" alt="SQL行转列应用的动态实现方式" src="https://zhuji.jb51.net/uploads/img/202305/b2fd21d5fb1c3b5aad0c044b65299628.jpg">
</center>
<h3>
总结一下:
</h3>
<p>
连续俩篇的文章更新,SQL行转列在项目中的应用都已经涵盖了。即将步入年底了,肯定有很多小伙伴被客户、领导追着搞各种报表,希望对小伙伴们有些许的帮助。
</p>
<p>
原文链接:https://www.toutiao.com/a7042121115925250571/
</p>
頁:
[1]