Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在sql select查询中使用分隔符重新排列字符串值_Sql_Select Query_Regexp Substr - Fatal编程技术网

在sql select查询中使用分隔符重新排列字符串值

在sql select查询中使用分隔符重新排列字符串值,sql,select-query,regexp-substr,Sql,Select Query,Regexp Substr,我有一个列,它的字符串值带有分隔符,如下所示,我在sql查询的select部分使用它 0040~0040~0040~0040~0040^00~00~00~01~05^100~001~010~011~015^00~00~00~01~05 单个磁头使用“^”分隔,如下所示 Head1 = 0040~0040~0040~0040~0040 Head2 = 00~00~00~01~05 Head3 = 100~001~010~011~015 Head4 = 00~00~00~01~05 所有4

我有一个列,它的字符串值带有分隔符,如下所示,我在sql查询的select部分使用它

0040~0040~0040~0040~0040^00~00~00~01~05^100~001~010~011~015^00~00~00~01~05
单个磁头使用“^”分隔,如下所示

Head1 = 0040~0040~0040~0040~0040

Head2 = 00~00~00~01~05

Head3 = 100~001~010~011~015

Head4 = 00~00~00~01~05
所有4个标题都有相同数量的条目,这些条目以“~”分隔,不一定是5个

我需要的是将所有4个头的第一个条目合并为一个。如下图所示

Head1 = 0040~0040~0040~0040~0040

Head2 = 00~00~00~01~05

Head3 = 100~001~010~011~015

Head4 = 00~00~00~01~05
0040-00-100-00由“-”分隔

然后是第二个条目,依此类推所有条目

如果条目数为4,如“我的字符串”,则格式化输出应如下所示:每个条目用逗号分隔:

0040-00-100-00,0040-00-001-00,0040-00-010-00,0040-01-011-01,
0040-05-015-05
我想在select查询中执行此操作,在该查询中获取此列值

例如

select x,y,z,(this is where I want this changes to be done.) from abc

您提出的问题不是一个容易解决的问题,它将您限制在select语句的内部。虽然您说过您不知道,但如果您知道每个字符串中有多少个头,您可以设置一个简单、复杂且非常长的select语句,其中字符串值具有名为foobar的分隔符:

SELECT x,y,z, SUBSTR(foobar, 1, INSTR(foobar, '~') - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '^') + 1, INSTR(foobar, '~', INSTR(foobar, '^')) - INSTR(foobar, '^') - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '^', 1, 2) + 1, INSTR(foobar, '~', INSTR(foobar, '^', 1, 2)) - INSTR(foobar, '^', 1, 2) - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '^', 1, 3) + 1, INSTR(foobar, '~', INSTR(foobar, '^', 1, 3)) - INSTR(foobar, '^', 1, 3) - 1) || ',' || SUBSTR(foobar, INSTR(foobar, '~') + 1, INSTR(foobar, '~', 1, 2) - INSTR(foobar, '~', 1, 1) - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '~', INSTR(foobar, '^', 1, 1)) + 1, INSTR(foobar, '~', INSTR(foobar, '^', 1, 1)) - INSTR(foobar, '^', 1, 1) - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '~', INSTR(foobar, '^', 1, 2)) + 1, INSTR(foobar, '~', INSTR(foobar, '^', 1, 2)) - INSTR(foobar, '^', 1, 2) - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '~', INSTR(foobar, '^', 1, 3)) + 1, INSTR(foobar, '~', INSTR(foobar, '^', 1, 3)) - INSTR(foobar, '^', 1, 3) - 1) 
FROM abc
这只会得到前两个条目,但是它会得到每个head,不管长度如何,它可以扩展到包含更多条目,但是如果只有两个条目,并且select语句扩展为五个条目,这是不可行的,因为您说过一行可以有任意数量的条目。有一种方法可以使用CASE语句来实现这一点,但它非常长,而且非常复杂。下面是一个示例查询,可能就是您要查找的:

SELECT x, y, z,
  CASE (LENGTH(SUBSTR(foobar, 1, INSTR(foobar, '^')))-LENGTH(REPLACE(SUBSTR(foobar, 1, INSTR(foobar, '^')), '~', '')) + 1)
    WHEN 1 THEN SUBSTR(foobar, 1, INSTR(foobar, '^') - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '^', 1, 1) + 1, INSTR(foobar, '^', 1, 2) - INSTR(foobar, '^', 1, 1) - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '^', 1, 2) + 1, INSTR(foobar, '^', 1, 3) - INSTR(foobar, '^', 1, 2) - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '^', 1, 3) + 1, LENGTH(foobar) - INSTR(foobar, '^', 1, 3))
    WHEN 2 THEN SUBSTR(foobar, 1, INSTR(foobar, '~') - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '^') + 1, INSTR(foobar, '~', INSTR(foobar, '^')) - INSTR(foobar, '^') - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '^', 1, 2) + 1, INSTR(foobar, '~', INSTR(foobar, '^', 1, 2)) - INSTR(foobar, '^', 1, 2) - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '^', 1, 3) + 1, INSTR(foobar, '~', INSTR(foobar, '^', 1, 3)) - INSTR(foobar, '^', 1, 3) - 1) || ',' || SUBSTR(foobar, INSTR(foobar, '~') + 1, INSTR(foobar, '^', 1, 1) - INSTR(foobar, '~', 1, 1) - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '~', INSTR(foobar, '^', 1, 1)) + 1, INSTR(foobar, '~', INSTR(foobar, '^', 1, 1), 1) - INSTR(foobar, '^', 1, 1) - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '~', INSTR(foobar, '^', 1, 2)) + 1, INSTR(foobar, '~', INSTR(foobar, '^', 1, 2)) - INSTR(foobar, '^', 1, 2) - 1) || '-' || SUBSTR(foobar, INSTR(foobar, '~', INSTR(foobar, '^', 1, 3)) + 1, INSTR(foobar, '~', INSTR(foobar, '^', 1, 3)) - INSTR(foobar, '^', 1, 3) - 1) 
    ELSE 'Too many entries: ' || (LENGTH(SUBSTR(foobar, 1, INSTR(foobar, '^')))-LENGTH(REPLACE(SUBSTR(foobar, 1, INSTR(foobar, '^')), '~', '')) + 1) || ' entries given of 2 maximum'
  END AS SAMPLE_OUTPUT
FROM abc;
当上述查询超出当前两个条目的容量时,将整理您的头脑。它非常长且复杂,但是如果您知道每个头的长度是恒定的,例如头1中每个条目的长度始终为4,那么如果在没有INSTR的情况下硬编码值,则可以缩短代码,从而加快执行速度。以下示例假设头部长度为4、2、3和2,如示例数据中所示:

SELECT x, y, z,
  CASE (LENGTH(SUBSTR(foobar, 1, INSTR(foobar, '^')))-LENGTH(REPLACE(SUBSTR(foobar, 1, INSTR(foobar, '^')), '~', '')) + 1)
    WHEN 1 THEN REPLACE(foobar, '^', '-')
    WHEN 2 THEN SUBSTR(foobar, 1, 4) || '-' || SUBSTR(foobar, 11, 2) || '-' || SUBSTR(foobar, 17, 3) || '-' || SUBSTR(foobar, 25, 2) || ',' || SUBSTR(foobar, 6, 4) || '-' || SUBSTR(foobar, 14, 2) || '-' || SUBSTR(foobar, 21, 3) || '-' || SUBSTR(foobar, 28, 2) 
    WHEN 3 THEN SUBSTR(foobar, 1, 4) || '-' || SUBSTR(foobar, 16, 2) || '-' || SUBSTR(foobar, 25, 3) || '-' || SUBSTR(foobar, 37, 2) || ',' || SUBSTR(foobar, 6, 4) || '-' || SUBSTR(foobar, 19, 2) || '-' || SUBSTR(foobar, 29, 3) || '-' || SUBSTR(foobar, 40, 2) || ',' || SUBSTR(foobar, 11, 4) || '-' || SUBSTR(foobar, 22, 2) || '-' || SUBSTR(foobar, 33, 3) || '-' || SUBSTR(foobar, 43, 2)
    ELSE 'Too many entries: ' || (LENGTH(SUBSTR(foobar, 1, INSTR(foobar, '^')))-LENGTH(REPLACE(SUBSTR(foobar, 1, INSTR(foobar, '^')), '~', '')) + 1) || ' entries given of 3 maximum'
  END AS SAMPLE_OUTPUT
FROM abc;

最后一点注意:我建议在case语句中使用列别名,因为如果您尝试在没有列别名的情况下测试代码,原因会变得非常明显。

第一个CTE只是选择创建虚拟记录,您可以忽略它。第二个CTE是递归的,用于按ID拆分^per上的列值,第三个CTE是组合以-分隔的节,使用XML per ID,最后一个CTE是将所有这些节组合成一个以、、分隔的字符串,。在合并所有内容之前,必须有一个ID列来分组。它将处理n行

;WITH myTable (id, MyColumn)
AS (SELECT 1, '0040~0040~0040~0040^00~00~00~01~05^100~001~010~011~015^00~00~00~01~05'
union ALL SELECT 2, 'b040~0040~0040~0040^b0~00~00~01~05^b00~001~010~011~015^b02~00~00~01~05'
union ALL SELECT 3, 'c040~0040~0040~0040^c0~00~00~01~05^c00~001~010~011~015^c02~00~00~01~05'
union ALL SELECT 4, 'd040~0040~0040~0040^d0~00~00~01~05^d00~001~010~011~015^d02~00~00~01~05'
),
RecursiveCTE (id, sub, startInd, endInd)
AS
(
    SELECT 
        id, 
        convert(varchar, SUBSTRING(MyColumn, 1, CHARINDEX('^', MyColumn ))) as sub
        , 0 AS startInd
        , CHARINDEX('^', MyColumn ) AS endInd
        from mytable
    UNION ALL
        select id,
        convert(varchar, SUBSTRING((SELECT MyColumn FROM myTable WHERE id = dr.id), endInd + 1, endInd - startInd)),
        endInd,
        CHARINDEX('^',  (SELECT MyColumn FROM myTable WHERE id = dr.id), endInd + 1) as endInd
    from RecursiveCTE dr
        where dr.endInd <> 0
),
PerIDSeperatedByDash AS (
select id,
STUFF((
select '-' + SUBSTRING(drinner.sub, 1, CHARINDEX('~', drinner.sub) - 1)
from RecursiveCTE drinner
WHERE (drinner.id = drouter.id)
FOR XML PATH ('')),1,1,'') AS DashSeperated
from RecursiveCTE drouter
group by id)
SELECT DISTINCT STUFF((
SELECT ',' + ds.DashSeperated
FROM PerIDSeperatedByDash ds
ORDER BY id
FOR XML PATH ('')),1,1,'') 
from PerIDSeperatedByDash 

您的行是否有ID列?是。但这不是解决这个问题所必需的。是的,如果有两个条目,这个就可以了。由于我的条目长度不是固定的,我必须找到另一种方法来解决这个问题。。谢谢你的回答@iamP第二个查询可以扩展以容纳更多条目。上面的示例最多只支持两个条目,但可以添加更多条目。如果您愿意,我将扩展查询以使其支持更多条目。条目可以接受任何数字。我想当数字变为5+甚至4+时,时间会长得多。你的代码很容易理解。有没有什么方法可以对任意数量的条目以某种方式迭代案例1,使其变得简短?@iamP如果每个head中的条目长度保持不变,就像Head1中的条目长度总是4个一样,然后,查询可以大大缩短,并且可能运行得更快,因为您可以在确定条目数后硬编码值,而不是在CASE语句中包含所有INSTR函数。我将在我的答案中添加一个例子。谢谢你的回答。我可以用刚才提到的select格式使用它吗?只是用代码替换最后一个select参数。如何使用?@iamP我认为您不能使用CTE作为内部选择。为什么它必须是select*from query here格式?