根据列值将单行拆分为更多列

时间:2017-04-19 13:52:05

标签: sql sql-server database tsql

如果给定列中存在任何特定值(在这种情况下为##;'),我需要获取3个类似的行数据集替换列值。例如

---------------------
Type     Value
---------------------
1        Apple[#]
2        Orange
3        Peach[#]

我需要修改查询以获取值,如下所示

 ----------------------
  Type        Value
 --------------------
   1         Apple1
   1         Apple2
   1         Apple3
   2         Orange
   3         Peach1
   3         Peach2
   3         Peach3

我无法想出如何获得这个

的逻辑

4 个答案:

答案 0 :(得分:1)

假设只有一个数字(如你的例子),那么我会选择:

with cte as (
      select (case when value like '%\[%%' then left(right(value, 2), 1) + 0
                   else 1
              end) as cnt, 1 as n,
             left(value, charindex('[', value + '[')) as base, type
      from t
      union all
      select cnt, n + 1, base, type
      from cte
      where n + 1 <= cnt
     )
select type,
       (case when cnt = 1 then base else concat(base, n) end) as value
from cte;

当然,CTE可以很容易地扩展到任意数量的数字:

(case when value like '%\[%%'
      then stuff(left(value, charindex(']')), 1, charindex(value, '['), '') + 0
      else 1
 end)

一旦你有了号码,就可以使用另一个号码来源。但递归CTE似乎是问题中特定问题的最简单解决方案。

答案 1 :(得分:1)

您也可以在没有递归的情况下获得相同的结果:

select Type, Value from MyTable where Right(Value, 3) <> '[#]'
union
select Type, Replace(Value, '[#]', '1') from MyTable where Right(Value, 3) = '[#]'
union
select Type, Replace(Value, '[#]', '2') from MyTable where Right(Value, 3) = '[#]'
union
select Type, Replace(Value, '[#]', '3') from MyTable where Right(Value, 3) = '[#]'

order by 1, 2

答案 2 :(得分:0)

尝试此查询

DECLARE @SampleData AS TABLE 
(
    Type int,
    Value varchar(100)
)

INSERT INTO @SampleData
VALUES (1, 'Apple[#]'), (2, 'Orange'), (3, 'Peach[#]')

SELECT sd.Type, cr.Value
FROM @SampleData sd
CROSS APPLY 
(
    SELECT TOP (IIF(Charindex('[#]', sd.Value) > 0, 3, 1)) 
            x.[Value] + Cast(v.t as nvarchar(5)) as Value
    FROM 
        (SELECT Replace(sd.Value, '[#]', '') AS Value) x
        Cross JOIN (VALUES (1),(2),(3)) v(t)
    Order by v.t asc

) cr

演示链接:Rextester

答案 3 :(得分:0)

使用递归CTE

import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.activation.DataHandler;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.List;

@Path("catalogos")
public class CatalogosREST {
    private final Logger log = LoggerFactory.getLogger(CatalogosREST.class);

    private String getFileName(MultivaluedMap<String, String> header) {
        String[] contentDisposition = header.getFirst("Content-Disposition").split(";");
        for (String filename : contentDisposition) {
            if ((filename.trim().startsWith("filename"))) {
                String[] name = filename.split("=");
                String exactFileName = name[1].trim().replaceAll("\"", "");
                return exactFileName;
            }
        }
        return "unknown";
    }

    @POST
    @Path("/upload")
    @Consumes("multipart/form-data")
    public Response uploadFile(List<Attachment> attachments, @Context HttpServletRequest request) {
        log.debug("se ha recibido una peticion para subir un archivo de proveedores [attachments: {}, request: {}]", attachments, request);
        Response response = null;
        for (Attachment attachment : attachments) {
            DataHandler handler = attachment.getDataHandler();
            try {
                InputStream stream = handler.getInputStream();
                MultivaluedMap<String, String> map = attachment.getHeaders();
                log.debug("headers: {}", map);
                log.debug("fileName: {}", getFileName(map));
                OutputStream out = new FileOutputStream(new File("/tmp/" + getFileName(map)));

                int read = 0;
                byte[] bytes = new byte[1024];
                while ((read = stream.read(bytes)) != -1) {
                    out.write(bytes, 0, read);
                }
                stream.close();
                out.flush();
                out.close();
                StringBuilder scriptOnFileUploadFinished = new StringBuilder(
                        "<script type=\"application/javascript\">\n" +
                                "      window.top.onFileUploadFinished();\n" +
                                "    </script>"
                );
                response = Response.ok(scriptOnFileUploadFinished.toString()).build();
            } catch (Exception e) {
                String error = "Ocurrio un error al subir el archivo de proveedores";
                log.error(error, e);
                response = Response.serverError().entity(error).build();
            }
        }
        return response;
    }
}