sql table vertical and horizontal expansion

First of all, the realization of vertical and horizontal table, Baidu, a lot, there is not a burden. I will put a picture so that we recall at the

     

 

There is a demand. For example export user address book, requires a user name when exporting, address 1, address 2, address 3 

But our data sheets are often designed so that

SELECT u.UserName, u.Address FROM users u

At this time, our export results if so

Past practice is to read the database, and then traverse the result set, the code slightly

If a sql query result set directly I want (as shown below)

Then I would not have to traverse the program.

Under review, in view of the beginning, the tables turn vertical cross table core statement in the case statement, there is an achievement which identifies the subject,

That being the case, the address book is not it also needs an identity column, then hands write sql statement, add one to the address book, this is the first of several addresses to identify

The code is simple

SELECT u.UserName, u.Address, ROW_NUMBER() over(partition by  u.UserName order by u.UserName desc) as AddressIndex FROM dbo.Users AS u

In this way, we came out a basic aspect of data conversion table.

In order to follow the code looks short, I decided to put the above statement in the statement on the CTE

WITH newUsers AS (
  SELECT u.UserName, u.Address, ROW_NUMBER() over(partition by u.UserName order by u.UserName desc) as AddressIndex FROM dbo.Users AS u
)

 Run the test cte statement

WITH newUsers AS (
  SELECT u.UserName, u.Address, ROW_NUMBER() over(partition by u.UserName order by u.UserName desc) as AddressIndex FROM dbo.Users AS u
)
SELECT * FROM newUsers

和没放在cte里的执行结果一致.

 

这时候再来写表转换

WITH newUsers AS (
  SELECT u.UserName, u.Address, ROW_NUMBER() over(partition by u.UserName order by u.UserName desc) as AddressIndex FROM dbo.Users AS u
)
SELECT a.UserName,
(CASE WHEN ( a.AddressIndex =1 ) THEN a.Address ELSE null END) as extAddress1,
(CASE WHEN ( a.AddressIndex =2 ) THEN a.Address ELSE null END) as extAddress2,
(CASE WHEN ( a.AddressIndex =3 ) THEN a.Address ELSE null END) as extAddress3
from newUsers a
GROUP BY a.UserName,a.AddressIndex,a.Address

 

发现大致样子出来了. ,但是1,2,3行应该合并起来

解决方法,给上面结果集嵌套一层,代码如下

WITH newUsers AS (
SELECT u.UserName, u.Address, ROW_NUMBER() over(partition by u.UserName order by u.UserName desc) as AddressIndex FROM dbo.Users AS u
)
SELECT aa.UserName, MAX(aa.extAddress1), MAX(aa.extAddress2), MAX(aa.extAddress3)
FROM (
SELECT a.UserName,
(CASE WHEN ( a.AddressIndex =1 ) THEN a.Address ELSE null END) as extAddress1,
(CASE WHEN ( a.AddressIndex =2 ) THEN a.Address ELSE null END) as extAddress2,
(CASE WHEN ( a.AddressIndex =3 ) THEN a.Address ELSE null END) as extAddress3
from newUsers a
GROUP BY a.UserName,a.AddressIndex,a.Address
) aa GROUP BY aa.UserName 

这样就出现了想要的结果集.

或许你会说,当地址簿有4个,5个或更多的地址的时候,sql修改起来麻烦,  但是我想说,代码根据业务逻辑来.这只是一个变化点,我满足当下需求,快速上线项目, 这个代码够用已经可以了.

当然你还可以用变量来解决sql语句的生成, 但是 这样一来代码就多了 ,具体代码实现我想小伙伴们花些时间就解决了.我在这里就不贴出代码, 给个友情提示把. 如果你要修改上面的代码,用变量实现, 此时CTE语句不能用,因为cte语句后面要紧跟select 语句 而不是 exec(sql变量) .

最后一点,关于这个sql的运行效率我没测试, 有心的小伙伴可以帮我留言.

 

 

 

 

 

 

   

 

Guess you like

Origin www.cnblogs.com/geliang/p/10962809.html