使用分隔符将SQL数据拆分为3列

时间:2016-04-05 20:30:10

标签: mysql sql-server excel vba excel-vba

我正在使用Excel VBA并使用OleDB连接到PGSQL。不幸的是,oledb不允许引用聚合函数之外的列,其中group by已应用于表,因此我必须连接数据,但是我无法将数据(latestBMI)拆分为3个单独的列( eventdate | weight | bmi),因为权重和bmi值的长度不同,但除以管道分隔符。

这是表格通过提取的样子:

master_id :   latestBMI
251       :   2008-05-08|84|26.8
2848      :   1992-11-23|86.71|27.3
2026      :   2002-04-16|105|31.6
22316     :   2014-02-28|107.955|35.1
16633     :   2005-07-04|70|25
9545      :   1997-04-08|82.73|24.9

我一直在尝试各种方法尝试SUBSTRING,CHARINDEX,LEN,LEFT | RIGHT,但失败了。 这是我目前的代码,但重量和bmi的SUBSTRING元素是我的问题:

Const sqlconnection = "Provider=oledb;"

Dim conn As New Connection
conn.ConnectionString = sqlconnection
conn.Open
Dim rs As Recordset

Sheets("Sheet1").Select
Range("A1").Select

Dim DATA As String
DATA = "SELECT latest.master_id, " _
& "SUBSTRING(latestBMI,1,10) eventdate, " _
& "SUBSTRING(latestBMI,12,CHARINDEX('|',latestBMI,RIGHT(latestBMI,7)) weight, " _
& "SUBSTRING(latestBMI,20,4) BMI " _
& "FROM ( " _
& "SELECT master_id, " _
& "MAX(CAST(eventdate AS VARCHAR(10)) + '|' + RIGHT(weightkg,7)+ '|' + RIGHT(bmi,4)) AS latestBMI " _
& "FROM weight " _
& "GROUP BY master_id) as latest " _
& "LEFT JOIN person p on latest.master_id = p.entity_id "

Set rs = conn.Execute(DATA)
With ActiveSheet.QueryTables.Add(Connection:=rs, Destination:=Range("A1"))
    .Refresh
End With

如何使用管道分隔符将它们分成3个单独的列?

4 个答案:

答案 0 :(得分:1)

我假设你的桌子有4列

master_id,BMI1,BMI2,BMI3和BMI4

您可以使用以下查询生成INSERT语句,然后在数据库上运行它们

select 'insert into newTable (master_id, BMI1, BMI2, BMI3) values( ' +
   cast(master_id as varchar) + ',''' + replace(latestBMI, '|', ''',''') + ''')'
from #t

它生成以下语句(使用您的示例数据)

insert into newTable (master_id, BMI1, BMI2, BMI3) values( 251,'2008-05-08','84','26.8')
insert into newTable (master_id, BMI1, BMI2, BMI3) values( 2848,'1992-11-23','86.71','27.3')
insert into newTable (master_id, BMI1, BMI2, BMI3) values( 2026,'2002-04-16','105','31.6')
insert into newTable (master_id, BMI1, BMI2, BMI3) values( 22316,'2014-02-28','107.955','35.1')
insert into newTable (master_id, BMI1, BMI2, BMI3) values( 16633,'2005-07-04','70','25')
insert into newTable (master_id, BMI1, BMI2, BMI3) values( 9545,'1997-04-08','82.73','24.9')

如果列不是整数,则可以修改SELECT语句以获得所需的内容。但是,即使您的列是数字的,生成的INSERT仍然有效。

答案 1 :(得分:0)

在导入数据的代码之后,只需使用text to columns将其分开。

    Sub SepDelCol()
       Columns("B:B").Select
       Selection.TextToColumns _
       Destination:=Range("B:B"), _
       DataType:=xlDelimited, _
       TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, _
       Tab:=False, Semicolon:=False, Comma:=False, Space:=False, _
       Other:=True, OtherChar:="|"
     End Sub

答案 2 :(得分:0)

如果您可以先获取数据,然后在表格中将其拆分,请尝试此操作(如果您知道最新的BMI数据将在B2:B7范围内)

  

Selection.TextToColumns目的地:=范围(“B2:B7”),_
  DataType:= xlDelimited,_
  TextQualifier:= xlDoubleQuote,_
  ConsecutiveDelimiter:= False,_
  Tab:= False,_
  分号:=假,逗号:=假,空格:=假,其他:=真,_
  OtherChar:=“|”,_
  FieldInfo:= Array(Array(1,1),Array(2,1),Array(3,1)),_
  TrailingMinusNumbers:=真

答案 3 :(得分:0)

有各种复杂的基于SQL /数据库的解决方案(请参阅Split Strings the Right Way),在SQL语句完成后,它将更容易在VBA中处理您的数据。

您的代码看起来会产生如下所示的结果:

enter image description here

因此,您应该遍历B列中的结果并将其分开。

Option Explicit

Sub test()
    SeparateFields ActiveSheet
End Sub

Sub SeparateFields(ws As Worksheet)
    '--- assumes your concatenated field (after your SQL
    '    statement) ends up in column B. The separated
    '    fields go in columns B, C, D.
    Dim concatFields As String
    Dim fields() As String
    Dim numRows As Long
    Dim i As Long
    numRows = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    For i = 2 To numRows
        concatFields = ws.Cells(i, 2).value
        fields = Split(concatFields, "|", , vbTextCompare)
        ws.Cells(i, 2).value = fields(0)
        ws.Cells(i, 3).value = fields(1)
        ws.Cells(i, 4).value = fields(2)
    Next i
End Sub