SQL 中的行转列和列转行
<p>行转列,列转行是我们在开发过程中经常碰到的问题。行转列一般通过CASE WHEN 语句来实现,也可以通过 SQL SERVER 的运算符PIVOT来实现。用传统的方法,比较好理解。层次清晰,而且比较习惯。 但是PIVOT 、UNPIVOT提供的语法比一系列复杂的SELECT…CASE 语句中所指定的语法更简单、更具可读性。下面我们通过几个简单的例子来介绍一下列转行、行转列问题。
</p>
<p>
<img title="SQL 中的行转列和列转行" alt="SQL 中的行转列和列转行" border="0" src="https://zhuji.jb51.net/uploads/img/202305/300b7bf9d0fc97206872a07129d1707f.jpg"></p>
<p>
我们首先先通过一个老生常谈的例子,学生成绩表(下面简化了些)来形象了解下行转列
</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">CREATE</span><span></span><span class="keyword">TABLE</span><span></span></span>
</li>
<li>
<span>(</span>
</li>
<li class="alt">
<span>NVARCHAR(20),<span class="comment">--学生姓名</span><span></span></span>
</li>
<li>
<span>NVARCHAR(30),<span class="comment">--科目</span><span></span></span>
</li>
<li class="alt">
<span><span class="keyword">FLOAT</span><span>,</span><span class="comment">--成绩</span><span></span></span>
</li>
<li>
<span>)</span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span></span><span class="keyword">SELECT</span><span></span><span class="string">'Nick'</span><span>,</span><span class="string">'语文'</span><span>,80</span></span>
</li>
<li class="alt">
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span></span><span class="keyword">SELECT</span><span></span><span class="string">'Nick'</span><span>,</span><span class="string">'数学'</span><span>,90</span></span>
</li>
<li>
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span></span><span class="keyword">SELECT</span><span></span><span class="string">'Nick'</span><span>,</span><span class="string">'英语'</span><span>,70</span></span>
</li>
<li class="alt">
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span></span><span class="keyword">SELECT</span><span></span><span class="string">'Nick'</span><span>,</span><span class="string">'生物'</span><span>,85</span></span>
</li>
<li>
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span></span><span class="keyword">SELECT</span><span></span><span class="string">'Kent'</span><span>,</span><span class="string">'语文'</span><span>,80</span></span>
</li>
<li class="alt">
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span></span><span class="keyword">SELECT</span><span></span><span class="string">'Kent'</span><span>,</span><span class="string">'数学'</span><span>,90</span></span>
</li>
<li>
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span></span><span class="keyword">SELECT</span><span></span><span class="string">'Kent'</span><span>,</span><span class="string">'英语'</span><span>,70</span></span>
</li>
<li class="alt">
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span></span><span class="keyword">SELECT</span><span></span><span class="string">'Kent'</span><span>,</span><span class="string">'生物'</span><span>,85</span></span>
</li>
</ol>
<p>
如果我想知道每位学生的每科成绩,而且每个学生的全部成绩排成一行,这样方便我查看、统计,导出数据
</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">SELECT</span><span></span></span>
</li>
<li>
<span>UserName,</span>
</li>
<li class="alt">
<span><span class="keyword">MAX</span><span>(</span><span class="func">CASE</span><span>Subject</span><span class="keyword">WHEN</span><span></span><span class="string">'语文'</span><span></span><span class="keyword">THEN</span><span>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 class="string">'语文'</span><span>,</span></span>
</li>
<li>
<span><span class="keyword">MAX</span><span>(</span><span class="func">CASE</span><span>Subject</span><span class="keyword">WHEN</span><span></span><span class="string">'数学'</span><span></span><span class="keyword">THEN</span><span>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 class="string">'数学'</span><span>,</span></span>
</li>
<li class="alt">
<span><span class="keyword">MAX</span><span>(</span><span class="func">CASE</span><span>Subject</span><span class="keyword">WHEN</span><span></span><span class="string">'英语'</span><span></span><span class="keyword">THEN</span><span>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 class="string">'英语'</span><span>,</span></span>
</li>
<li>
<span><span class="keyword">MAX</span><span>(</span><span class="func">CASE</span><span>Subject</span><span class="keyword">WHEN</span><span></span><span class="string">'生物'</span><span></span><span class="keyword">THEN</span><span>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 class="string">'生物'</span><span></span></span>
</li>
<li class="alt">
<span><span class="keyword">FROM</span><span>dbo.</span></span>
</li>
<li>
<span><span class="keyword">GROUP</span><span></span><span class="keyword">BY</span><span>UserName</span></span>
</li>
</ol>
<p>
查询结果如图所示,这样我们就能很清楚的了解每位学生所有的成绩了
</p>
<p>
<img title="SQL 中的行转列和列转行" alt="SQL 中的行转列和列转行" border="0" src="https://zhuji.jb51.net/uploads/img/202305/52c8934a93cd822e7dc68aa16e632345.jpg"></p>
<p>
接下来我们来看看第二个小列子。有一个游戏玩家充值表(仅仅为了说明,举的一个小例子),
</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">CREATE</span><span></span><span class="keyword">TABLE</span><span></span></span>
</li>
<li>
<span>(</span>
</li>
<li class="alt">
<span><span class="keyword">INT</span><span>IDENTITY(1,1),</span></span>
</li>
<li>
<span>NVARCHAR(20),<span class="comment">--游戏玩家</span><span></span></span>
</li>
<li class="alt">
<span>DATETIME,<span class="comment">--充值时间</span><span></span></span>
</li>
<li>
<span>NVARCHAR(20),<span class="comment">--充值类型</span><span></span></span>
</li>
<li class="alt">
<span><span class="keyword">DECIMAL</span><span>,</span><span class="comment">--充值金额</span><span></span></span>
</li>
<li>
<span><span class="keyword">BIT</span><span>,</span><span class="comment">--是否成功1表示成功,0表示失败</span><span></span></span>
</li>
<li class="alt">
<span><span class="keyword">CONSTRAINT</span><span></span><span class="keyword">PRIMARY</span><span></span><span class="keyword">KEY</span><span>(ID)</span></span>
</li>
<li>
<span>)</span>
</li>
<li class="alt">
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span>Inpours</span><span class="keyword">SELECT</span><span></span><span class="string">'张三'</span><span>,</span><span class="string">'2010-05-01'</span><span>,</span><span class="string">'支付宝'</span><span>,50,1</span></span>
</li>
<li>
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span>Inpours</span><span class="keyword">SELECT</span><span></span><span class="string">'张三'</span><span>,</span><span class="string">'2010-06-14'</span><span>,</span><span class="string">'支付宝'</span><span>,50,1</span></span>
</li>
<li class="alt">
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span>Inpours</span><span class="keyword">SELECT</span><span></span><span class="string">'张三'</span><span>,</span><span class="string">'2010-06-14'</span><span>,</span><span class="string">'手机短信'</span><span>,100,1</span></span>
</li>
<li>
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span>Inpours</span><span class="keyword">SELECT</span><span></span><span class="string">'李四'</span><span>,</span><span class="string">'2010-06-14'</span><span>,</span><span class="string">'手机短信'</span><span>,100,1</span></span>
</li>
<li class="alt">
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span>Inpours</span><span class="keyword">SELECT</span><span></span><span class="string">'李四'</span><span>,</span><span class="string">'2010-07-14'</span><span>,</span><span class="string">'支付宝'</span><span>,100,1</span></span>
</li>
<li>
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span>Inpours</span><span class="keyword">SELECT</span><span></span><span class="string">'王五'</span><span>,</span><span class="string">'2010-07-14'</span><span>,</span><span class="string">'工商银行卡'</span><span>,100,1</span></span>
</li>
<li class="alt">
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span>Inpours</span><span class="keyword">SELECT</span><span></span><span class="string">'赵六'</span><span>,</span><span class="string">'2010-07-14'</span><span>,</span><span class="string">'建设银行卡'</span><span>,100,1</span></span>
</li>
</ol>
<p>
下面来了一个统计数据的需求,要求按日期、支付方式来统计充值金额信息。这也是一个典型的行转列的例子。我们可以通过下面的脚本来达到目的
</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">SELECT</span><span></span></span>
</li>
<li>
<span><span class="func">CONVERT</span><span>(</span><span class="keyword">VARCHAR</span><span>(10),CreateTime,120)</span><span class="keyword">AS</span><span>CreateTime,</span></span>
</li>
<li class="alt">
<span><span class="func">CASE</span><span>PayType</span><span class="keyword">WHEN</span><span></span><span class="string">'支付宝'</span><span></span><span class="keyword">THEN</span><span></span><span class="func">SUM</span><span>(Money)</span><span class="keyword">ELSE</span><span>0</span><span class="keyword">END</span><span></span><span class="keyword">AS</span><span></span><span class="string">'支付宝'</span><span>,</span></span>
</li>
<li>
<span><span class="func">CASE</span><span>PayType</span><span class="keyword">WHEN</span><span></span><span class="string">'手机短信'</span><span></span><span class="keyword">THEN</span><span></span><span class="func">SUM</span><span>(Money)</span><span class="keyword">ELSE</span><span>0</span><span class="keyword">END</span><span></span><span class="keyword">AS</span><span></span><span class="string">'手机短信'</span><span>,</span></span>
</li>
<li class="alt">
<span><span class="func">CASE</span><span>PayType</span><span class="keyword">WHEN</span><span></span><span class="string">'工商银行卡'</span><span></span><span class="keyword">THEN</span><span></span><span class="func">SUM</span><span>(Money)</span><span class="keyword">ELSE</span><span>0</span><span class="keyword">END</span><span></span><span class="keyword">AS</span><span></span><span class="string">'工商银行卡'</span><span>,</span></span>
</li>
<li>
<span><span class="func">CASE</span><span>PayType</span><span class="keyword">WHEN</span><span></span><span class="string">'建设银行卡'</span><span></span><span class="keyword">THEN</span><span></span><span class="func">SUM</span><span>(Money)</span><span class="keyword">ELSE</span><span>0</span><span class="keyword">END</span><span></span><span class="keyword">AS</span><span></span><span class="string">'建设银行卡'</span><span></span></span>
</li>
<li class="alt">
<span><span class="keyword">FROM</span><span>Inpours</span></span>
</li>
<li>
<span><span class="keyword">GROUP</span><span></span><span class="keyword">BY</span><span>CreateTime,PayType</span></span>
</li>
</ol>
<p>
如图所示,我们这样只是得到了这样的输出结果,还需进一步处理,才能得到想要的结果
</p>
<p>
<img title="SQL 中的行转列和列转行" alt="SQL 中的行转列和列转行" border="0" src="https://zhuji.jb51.net/uploads/img/202305/64740c45b130cc4555a944338424cdc8.jpg"></p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">SELECT</span><span></span></span>
</li>
<li>
<span>CreateTime,</span>
</li>
<li class="alt">
<span><span class="func">ISNULL</span><span>(</span><span class="func">SUM</span><span>([支付宝]),0)</span><span class="keyword">AS</span><span>[支付宝],</span></span>
</li>
<li>
<span><span class="func">ISNULL</span><span>(</span><span class="func">SUM</span><span>([手机短信]),0)</span><span class="keyword">AS</span><span>[手机短信],</span></span>
</li>
<li class="alt">
<span><span class="func">ISNULL</span><span>(</span><span class="func">SUM</span><span>([工商银行卡]),0)</span><span class="keyword">AS</span><span>[工商银行卡],</span></span>
</li>
<li>
<span><span class="func">ISNULL</span><span>(</span><span class="func">SUM</span><span>([建设银行卡]),0)</span><span class="keyword">AS</span><span>[建设银行卡]</span></span>
</li>
<li class="alt">
<span><span class="keyword">FROM</span><span></span></span>
</li>
<li>
<span>(</span>
</li>
<li class="alt">
<span><span class="keyword">SELECT</span><span></span></span>
</li>
<li>
<span><span class="func">CONVERT</span><span>(</span><span class="keyword">VARCHAR</span><span>(10),CreateTime,120)</span><span class="keyword">AS</span><span>CreateTime,</span></span>
</li>
<li class="alt">
<span><span class="func">CASE</span><span>PayType</span><span class="keyword">WHEN</span><span></span><span class="string">'支付宝'</span><span></span><span class="keyword">THEN</span><span></span><span class="func">SUM</span><span>(Money)</span><span class="keyword">ELSE</span><span>0</span><span class="keyword">END</span><span></span><span class="keyword">AS</span><span></span><span class="string">'支付宝'</span><span>,</span></span>
</li>
<li>
<span><span class="func">CASE</span><span>PayType</span><span class="keyword">WHEN</span><span></span><span class="string">'手机短信'</span><span></span><span class="keyword">THEN</span><span></span><span class="func">SUM</span><span>(Money)</span><span class="keyword">ELSE</span><span>0</span><span class="keyword">END</span><span></span><span class="keyword">AS</span><span></span><span class="string">'手机短信'</span><span>,</span></span>
</li>
<li class="alt">
<span><span class="func">CASE</span><span>PayType</span><span class="keyword">WHEN</span><span></span><span class="string">'工商银行卡'</span><span></span><span class="keyword">THEN</span><span></span><span class="func">SUM</span><span>(Money)</span><span class="keyword">ELSE</span><span>0</span><span class="keyword">END</span><span></span><span class="keyword">AS</span><span></span><span class="string">'工商银行卡'</span><span>,</span></span>
</li>
<li>
<span><span class="func">CASE</span><span>PayType</span><span class="keyword">WHEN</span><span></span><span class="string">'建设银行卡'</span><span></span><span class="keyword">THEN</span><span></span><span class="func">SUM</span><span>(Money)</span><span class="keyword">ELSE</span><span>0</span><span class="keyword">END</span><span></span><span class="keyword">AS</span><span></span><span class="string">'建设银行卡'</span><span></span></span>
</li>
<li class="alt">
<span><span class="keyword">FROM</span><span>Inpours</span></span>
</li>
<li>
<span><span class="keyword">GROUP</span><span></span><span class="keyword">BY</span><span>CreateTime,PayType</span></span>
</li>
<li class="alt">
<span>)T</span>
</li>
<li>
<span><span class="keyword">GROUP</span><span></span><span class="keyword">BY</span><span>CreateTime</span></span>
</li>
</ol>
<p>
其实行转列,关键是要理清逻辑,而且对分组(Group by)概念比较清晰。上面两个列子基本上就是行转列的类型了。但是有个问题来了,上面是我为了说明弄的一个简单列子。实际中,可能支付方式特别多,而且逻辑也复杂很多,可能涉及汇率、手续费等等(曾经做个这样一个),如果支付方式特别多,我们的CASE WHEN 会弄出一大堆,确实比较恼火,而且新增一种支付方式,我们还得修改脚本如果把上面的脚本用动态SQL改写一下,我们就能轻松解决这个问题
</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">DECLARE</span><span>@cmdText</span><span class="keyword">VARCHAR</span><span>(8000);</span></span>
</li>
<li>
<span><span class="keyword">DECLARE</span><span>@tmpSql</span><span class="keyword">VARCHAR</span><span>(8000);</span></span>
</li>
<li class="alt">
<span><span class="keyword">SET</span><span>@cmdText=</span><span class="string">'SELECTCONVERT(VARCHAR(10),CreateTime,120)ASCreateTime,'</span><span>+</span><span class="keyword">CHAR</span><span>(10);</span></span>
</li>
<li>
<span><span class="keyword">SELECT</span><span>@cmdText=@cmdText+</span><span class="string">'CASEPayTypeWHEN'</span><span class="string">''</span><span>+</span></span>
</li>
<li class="alt">
<span>PayType+<span class="string">''</span><span class="string">'THENSUM(Money)ELSE0ENDAS'</span><span class="string">''</span><span>+PayType</span></span>
</li>
<li>
<span>+<span class="string">''</span><span class="string">','</span><span>+</span><span class="keyword">CHAR</span><span>(10)</span><span class="keyword">FROM</span><span>(</span><span class="keyword">SELECT</span><span></span><span class="keyword">DISTINCT</span><span>PayType</span><span class="keyword">FROM</span><span>Inpours)T</span></span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span><span class="keyword">SET</span><span>@cmdText=</span><span class="func">LEFT</span><span>(@cmdText,LEN(@cmdText)-2)</span><span class="comment">--注意这里,如果没有加CHAR(10)则用LEFT(@cmdText,LEN(@cmdText)-1)</span><span></span></span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span><span class="keyword">SET</span><span>@cmdText=@cmdText+'</span><span class="keyword">FROM</span><span>Inpours</span></span>
</li>
<li class="alt">
<span><span class="keyword">GROUP</span><span></span><span class="keyword">BY</span><span>CreateTime,PayType';</span></span>
</li>
<li>
<span></span>
</li>
<li class="alt">
<span><span class="keyword">SET</span><span>@tmpSql=</span><span class="string">'SELECTCreateTime,'</span><span>+</span><span class="keyword">CHAR</span><span>(10);</span></span>
</li>
<li>
<span><span class="keyword">SELECT</span><span>@tmpSql=@tmpSql+</span><span class="string">'ISNULL(SUM('</span><span>+PayType+</span><span class="string">'),0)AS'</span><span class="string">''</span><span>+</span></span>
</li>
<li class="alt">
<span>PayType+<span class="string">''</span><span class="string">','</span><span>+</span><span class="keyword">CHAR</span><span>(10)</span></span>
</li>
<li>
<span><span class="keyword">FROM</span><span>(</span><span class="keyword">SELECT</span><span></span><span class="keyword">DISTINCT</span><span>PayType</span><span class="keyword">FROM</span><span>Inpours)T</span></span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span><span class="keyword">SET</span><span>@tmpSql=</span><span class="func">LEFT</span><span>(@tmpSql,LEN(@tmpSql)-2)+</span><span class="string">'FROM('</span><span>+</span><span class="keyword">CHAR</span><span>(10);</span></span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span><span class="keyword">SET</span><span>@cmdText=@tmpSql+@cmdText+</span><span class="string">')TGROUPBYCreateTime'</span><span>;</span></span>
</li>
<li class="alt">
<span>PRINT@cmdText</span>
</li>
<li>
<span><span class="keyword">EXECUTE</span><span>(@cmdText);</span></span>
</li>
</ol>
<p>
下面是通过PIVOT来进行行转列的用法,大家可以对比一下,确实要简单、更具可读性
</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">SELECT</span><span>CreateTime,[支付宝],[手机短信],[工商银行卡],[建设银行卡]</span></span>
</li>
<li>
<span><span class="keyword">FROM</span><span></span></span>
</li>
<li class="alt">
<span>(</span>
</li>
<li>
<span><span class="keyword">SELECT</span><span></span><span class="func">CONVERT</span><span>(</span><span class="keyword">VARCHAR</span><span>(10),CreateTime,120)</span><span class="keyword">AS</span><span>CreateTime,PayType,Money</span></span>
</li>
<li class="alt">
<span><span class="keyword">FROM</span><span>Inpours</span></span>
</li>
<li>
<span>)P</span>
</li>
<li class="alt">
<span>PIVOT(</span>
</li>
<li>
<span><span class="func">SUM</span><span>(Money)</span></span>
</li>
<li class="alt">
<span><span class="keyword">FOR</span><span>PayType</span><span class="op">IN</span><span></span></span>
</li>
<li>
<span>([支付宝],[手机短信],[工商银行卡],[建设银行卡])</span>
</li>
<li class="alt">
<span>)<span class="keyword">AS</span><span>T</span></span>
</li>
<li>
<span><span class="keyword">ORDER</span><span></span><span class="keyword">BY</span><span>CreateTime</span></span>
</li>
</ol>
<p>
有时可能会出现这样的错误:
</p>
<p>
消息 325,级别 15,状态 1,第 9 行
</p>
<p>
‘PIVOT’ 附近有语法错误。您可能需要将当前数据库的兼容级别设置为更高的值,以启用此功能。有关存储过程 sp_dbcmptlevel 的信息,请参见帮助。
</p>
<p>
这个是因为:对升级到 SQL Server 2005 或更高版本的数据库使用 PIVOT 和 UNPIVOT 时,必须将数据库的兼容级别设置为 90 或更高。有关如何设置数据库兼容级别的信息,请参阅 sp_dbcmptlevel (Transact-SQL)。 例如,只需在执行上面脚本前加上 EXEC sp_dbcmptlevel Test, 90; 就OK了, Test 是所在数据库的名称。
</p>
<p>
下面我们来看看列转行,主要是通过UNION ALL ,MAX来实现。假如有下面这么一个表
</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">Create</span><span></span><span class="keyword">Table</span><span>ProgrectDetail</span></span>
</li>
<li>
<span>(</span>
</li>
<li class="alt">
<span>ProgrectNameNVARCHAR(20),<span class="comment">--工程名称</span><span></span></span>
</li>
<li>
<span>OverseaSupply<span class="keyword">INT</span><span>,</span><span class="comment">--海外供应商供给数量</span><span></span></span>
</li>
<li class="alt">
<span>NativeSupply<span class="keyword">INT</span><span>,</span><span class="comment">--国内供应商供给数量</span><span></span></span>
</li>
<li>
<span>SouthSupply<span class="keyword">INT</span><span>,</span><span class="comment">--南方供应商供给数量</span><span></span></span>
</li>
<li class="alt">
<span>NorthSupply<span class="keyword">INT</span><span></span><span class="comment">--北方供应商供给数量</span><span></span></span>
</li>
<li>
<span>)</span>
</li>
<li class="alt">
<span></span>
</li>
<li>
<span><span class="keyword">INSERT</span><span></span><span class="keyword">INTO</span><span>ProgrectDetail</span></span>
</li>
<li class="alt">
<span><span class="keyword">SELECT</span><span></span><span class="string">'A'</span><span>,100,200,50,50</span></span>
</li>
<li>
<span><span class="keyword">UNION</span><span></span><span class="op">ALL</span><span></span></span>
</li>
<li class="alt">
<span><span class="keyword">SELECT</span><span></span><span class="string">'B'</span><span>,200,300,150,150</span></span>
</li>
<li>
<span><span class="keyword">UNION</span><span></span><span class="op">ALL</span><span></span></span>
</li>
<li class="alt">
<span><span class="keyword">SELECT</span><span></span><span class="string">'C'</span><span>,159,400,20,320</span></span>
</li>
<li>
<span><span class="keyword">UNION</span><span></span><span class="op">ALL</span><span></span></span>
</li>
<li class="alt">
<span><span class="keyword">SELECT</span><span></span><span class="string">'D'</span><span>,250,30,15,15</span></span>
</li>
</ol>
<p>
我们可以通过下面的脚本来实现,查询结果如下图所示
</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">SELECT</span><span>ProgrectName,</span><span class="string">'OverseaSupply'</span><span></span><span class="keyword">AS</span><span>Supplier,</span></span>
</li>
<li>
<span><span class="keyword">MAX</span><span>(OverseaSupply)</span><span class="keyword">AS</span><span></span><span class="string">'SupplyNum'</span><span></span></span>
</li>
<li class="alt">
<span><span class="keyword">FROM</span><span>ProgrectDetail</span></span>
</li>
<li>
<span><span class="keyword">GROUP</span><span></span><span class="keyword">BY</span><span>ProgrectName</span></span>
</li>
<li class="alt">
<span><span class="keyword">UNION</span><span></span><span class="op">ALL</span><span></span></span>
</li>
<li>
<span><span class="keyword">SELECT</span><span>ProgrectName,</span><span class="string">'NativeSupply'</span><span></span><span class="keyword">AS</span><span>Supplier,</span></span>
</li>
<li class="alt">
<span><span class="keyword">MAX</span><span>(NativeSupply)</span><span class="keyword">AS</span><span></span><span class="string">'SupplyNum'</span><span></span></span>
</li>
<li>
<span><span class="keyword">FROM</span><span>ProgrectDetail</span></span>
</li>
<li class="alt">
<span><span class="keyword">GROUP</span><span></span><span class="keyword">BY</span><span>ProgrectName</span></span>
</li>
<li>
<span><span class="keyword">UNION</span><span></span><span class="op">ALL</span><span></span></span>
</li>
<li class="alt">
<span><span class="keyword">SELECT</span><span>ProgrectName,</span><span class="string">'SouthSupply'</span><span></span><span class="keyword">AS</span><span>Supplier,</span></span>
</li>
<li>
<span><span class="keyword">MAX</span><span>(SouthSupply)</span><span class="keyword">AS</span><span></span><span class="string">'SupplyNum'</span><span></span></span>
</li>
<li class="alt">
<span><span class="keyword">FROM</span><span>ProgrectDetail</span></span>
</li>
<li>
<span><span class="keyword">GROUP</span><span></span><span class="keyword">BY</span><span>ProgrectName</span></span>
</li>
<li class="alt">
<span><span class="keyword">UNION</span><span></span><span class="op">ALL</span><span></span></span>
</li>
<li>
<span><span class="keyword">SELECT</span><span>ProgrectName,</span><span class="string">'NorthSupply'</span><span></span><span class="keyword">AS</span><span>Supplier,</span></span>
</li>
<li class="alt">
<span><span class="keyword">MAX</span><span>(NorthSupply)</span><span class="keyword">AS</span><span></span><span class="string">'SupplyNum'</span><span></span></span>
</li>
<li>
<span><span class="keyword">FROM</span><span>ProgrectDetail</span></span>
</li>
<li class="alt">
<span><span class="keyword">GROUP</span><span></span><span class="keyword">BY</span><span>ProgrectName</span></span>
</li>
</ol>
<p>
<img title="SQL 中的行转列和列转行" alt="SQL 中的行转列和列转行" border="0" src="https://zhuji.jb51.net/uploads/img/202305/6a2bd773e3e9128d7b87af2176ed367c.jpg"></p>
<p>
用UNPIVOT 实现如下:
</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">SELECT</span><span>ProgrectName,Supplier,SupplyNum</span></span>
</li>
<li>
<span><span class="keyword">FROM</span><span></span></span>
</li>
<li class="alt">
<span>(</span>
</li>
<li>
<span><span class="keyword">SELECT</span><span>ProgrectName,OverseaSupply,NativeSupply,</span></span>
</li>
<li class="alt">
<span>SouthSupply,NorthSupply</span>
</li>
<li>
<span><span class="keyword">FROM</span><span>ProgrectDetail</span></span>
</li>
<li class="alt">
<span>)T</span>
</li>
<li>
<span>UNPIVOT</span>
</li>
<li class="alt">
<span>(</span>
</li>
<li>
<span>SupplyNum<span class="keyword">FOR</span><span>Supplier</span><span class="op">IN</span><span></span></span>
</li>
<li class="alt">
<span>(OverseaSupply,NativeSupply,SouthSupply,NorthSupply)</span>
</li>
<li>
<span>)P</span>
</li>
</ol>
<p>
原文链接:https://mp.weixin.qq.com/s?__biz=MzA3MTg4NjY4Mw==&mid=2457323770&idx=2&sn=d3209bed52a39106bbe452a9a5b35b3c&chksm=88a5dacebfd253d8acaf8278b10e3b8331ed12b4fcb41eaab6a6d05cae82869ad56111e1a6b2&mpshare=1&
</p>
頁:
[1]