从随机排序列中按顺序提取数字

时间:2019-04-24 08:50:46

标签: postgresql

我的数据库 class Point3d: ...... def distance_from_origin(self): temp_x = self.x ** 2 temp_y = self.y ** 2 temp_z = self.z ** 2 return ((temp_x) + (temp_y) + (temp_z)) ** 0.5 def area_of_sphere(self): return (4 * math.pi * (self.distance_from_origin())**2) def __eq__(self, object): if self.x == object.x and self.y == object.y and self.z == object.z: return True else: return False def __str__(self): return str(self.x) + " , " + str(self.y) + " , " + str(self.z) 中只有一列,其中包含一系列多选选项1-4,这些选项可以以任意随机顺序出现,并以空格分隔,例如qs51 2 4

我想将这些选项中的每一个都提取到其自己的列中,这样我就得到了列4 1-qs5c1,这样上面的示例看起来像

qs5c4

这是我一直在使用的SQL

|qs5c1|qs5c2|qs5c3|qs5c4|
|-----|-----|-----|-----|
|  1  |  2  |null |  4  |
|  1  |null |null |  4  |

但是,以上面的数据为例,我所得到的是这样,它只选择字符串中的第一个字符,然后跳过其余的字符。

substring('1' from position('1' in qs5) for 1) as qs5c1,
substring('2' from position('2' in qs5) for 1) as qs5c2,
substring('3' from position('3' in qs5) for 1) AS qs5c3,
substring('4' from position('4' in qs5) for 1) AS qs5c4

我在想,当提取第一个字符时,|qs5c1|qs5c2|qs5c3|qs5c4| |-----|-----|-----|-----| | 1 |null |null |null | |null |null |null | 4 | 的长度比以前小了1个字符,但是这又不能解释为什么第二行跳过了1,因为1提取4之前/之后应该在同一位置。

谢谢!

2 个答案:

答案 0 :(得分:1)

问题是,您不是substring()中的qs5,而是文字'1''2'等。因此,这当然只能导致单个字符从字面上看。如果您使用qs5则可以正常使用。

SELECT substring(qs5 FROM position('1' IN qs5) FOR 1) qs5c1,
       substring(qs5 FROM position('2' IN qs5) FOR 1) qs5c2,
       substring(qs5 FROM position('3' IN qs5) FOR 1) qs5c3,
       substring(qs5 FROM position('4' IN qs5) FOR 1) qs5c4
       FROM elbat;

db<>fiddle

答案 1 :(得分:0)

如果它确实是一组固定值,我会这样做:

select case when '1' = any(string_to_array(qs5, ' ')) then '1' end as qs51,
       case when '2' = any(string_to_array(qs5, ' ')) then '2' end as qs52,
       case when '3' = any(string_to_array(qs5, ' ')) then '3' end as qs53,
       case when '4' = any(string_to_array(qs5, ' ')) then '4' end as qs54,
       case when '5' = any(string_to_array(qs5, ' ')) then '5' end as qs55
from the_table;

在线示例:https://rextester.com/FMR86051

如果您需要更动态的方式,则可以使用以下方式:

select f.options[1] as qs5c1,
       f.options[2] as qs5c2,
       f.options[3] as qs5c3,
       f.options[4] as qs5c4
from the_table t
  cross join lateral (
    select array_agg(x.val order by g.idx) as options
    from generate_series(1,4) g(idx)
      left join unnest(string_to_array(t.qs5, ' ')::int[]) with ordinality as x(val,idx) on g.idx = x.val
  ) f
;

具有8个元素的在线示例:https://rextester.com/PMKDW38472