如何按多个条件拆分列?

时间:2016-11-03 16:10:30

标签: sql oracle ms-access split

背景

我有一张约90万人的表(1875年的人口普查)。我正在创建犯罪分子名单,我正试图找到跟随父母入狱的孩子。为此,我使用两个表:表1包含所有罪犯;表2包含每个人。我想在表2中搜索表1中列出的人,并且年龄在0-15岁之间。

制备

在清洁桌子时,我已经选择了大约6 000个无法轻易选择和/或清洁的桌子。数据结构的主要部分如下:

These collectively identify each individual           Not part of table
┌───────┴───────┐                                     ┌───────────┴───────────┐
ID1  ID2 ID3  ID4 FNAME   LNAME        BYEAR          *comment*
0515 004 0072 006 Ole     Jacobsen     1825@1826      usable
0515 004 0072 007 Gunhild Thorsdatter  1831@1835      possibly usable
0515 004 0075 010 Hans    Johnsden     1875@1865      unusable
0515 004 0099 001 Marit   Jakobsdatter 1832??@1837??  usable
0515 004 0102 193 Arne    Olsen        1836 %1805%    usable
0515 004 0102 194 Rasmus  Pedersen     1876!!         usable after corrections

说明:

  • @符号表示''或''
  • A ??表示不确定性
  • A !!表示源实际包含此错误信息
  • %[text]%表示文字在源
  • 中受到影响

方法和主要问题

我打算做的是列出BYEAR被列为YYYY@YYYY(第1年[或]年2)的每个人;我可以使用like "*@*"执行此操作。但是,我也希望将BYEAR中的信息分为三列:BYEAR1 BYEARJUNK(参见注释3)BYEAR2。从这些专栏中,我可以用干净的数字来计算年龄差异,从而找到可以进行进一步研究的个体。

所以我在标题中重复并澄清我的问题:如何将BYEAR列拆分为三个(或更多)列,以@或空格作为分隔符?

注释

1

其他人提出了类似的问题,但是this one是关于Unix的,this other post通过不分割数据来回答问题,我需要做的是执行计算(因此其他人可以轻松地重现我的方法) )。

2

我添加了Oracle标记。但是,我目前正在本地工作,但将来需要对服务器进行相同的操作。

3

以上并未明确说明应如何填充垃圾栏。它的功能是列出从初始分隔符到最终分隔符的所有内容。以下是基本规则:

方法1

  • 如果有@,BYEAR可以被认为只有一个分隔符。 BYEAR1将由@和BYEAR2之前的所有内容填充; BYEARJUNK只包含@。
  • 如果第一年后有空格 - 例如“1802? eller 1808'或'1802 ??埃勒蚂蚁。 1808',BYEARJUNK应分别由'eller'和'eller ant填充。 '(包括空格)。
  • 但是,如果有空格是@符号,例如“1802? eller 1803 @ 1808'?在这种情况下,我会将第一个空格作为初始分隔符,将(最终)@作为最终分隔符。换句话说:BYEAR1:'1802 ??'; BYEARJUNK:'eller 1803 @'; BYEAR2:'1808'。

方法2

就像这样:@和空格总是被视为分隔符;因此,要创建的BYEARJUNK列的数量将等于具有最多字数(减去2)的字段。这种方法可能是最简单和最好的方法,因为之后可以轻松地隔离感兴趣的数据。 BYEAR1BYEAR2应该始终是该字段数据的第一个也是最后一个部分。

2 个答案:

答案 0 :(得分:0)

对于已清理的数据集,即始终有四个数字后跟分隔符(此处为@)后跟四个数字,以下代码可解决此问题。注意:我已将字段的名称更改为L[eft]BYEARR[ight]BYEAR,并且尚未创建垃圾列,因为数据已清除

SELECT
LEFT ([BYEAR], 4) AS LBYEAR,
RIGHT([BYEAR], 4) AS RBYEAR,
(LBYEAR-RBYEAR)   AS ΣBYEARDIFF,
*

FROM [mytable]

WHERE BYEAR like "*@*";

这会创建三列:

  • LBYEARBYEAR列中找到前四个字符(希望是数字)。
  • RBYEARBYEAR列中找到最后四个字符(希望是数字)。
  • ΣBYEARDIFF计算差异。

最后一列非常有用,因为它会返回可以提取正确数据的字段的错误,即数据尚未清除的字段。输出示例:

LBYEAR  RBYEAR  ΣBYEARDIFF  PERSNR  FORNVN      ETTNVN          FAAR
1857    1847    10          005     Dorthea     Evensen         1857@1847
1845    1847    -2          002     Katharine   Olsdatter Ovren 1838@1837
22.0    1825    #Error      002     Boel Karin  Amundsen        22.06@07.1825
1857    1867    -10         008     Thrine  Andersen            1857@1867
1858    1857    1           027     Karl Georg  Syvertsen       1858@1857

使用此列,可以 - 根据研究的要求 - 首先使用WHERE ΣBYEARDIFF BETWEEN n and m选择要包含在最终清理步骤中的行,例如WHERE ΣBYEARDIFF BETWEEN -2 and 2将接受的数据插入到新表中,然后运行更新查询(见下文)以删除前四位数字(在本例中为字符,恰好是数字)。

代码:

UPDATE [T with accepted data]

SET BYEAR = left(BYEAR, 4)
WHERE BYEAR like "????*";

答案 1 :(得分:-1)

是否总共有2个日期由@?

分隔
left(byear,instr(byear,"@")-1)

会在@

之前给你一些字符
mid(byear,instr(byear,"@")+1)

会在@

之后给你字符