How to retrieve multi-row blocks from a datatable?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • John Dann

    How to retrieve multi-row blocks from a datatable?

    Is there a concise/efficient way to retrieve blocks of rows from a
    datatable with VB2005?

    I've got a datatable (let's call it AllData), constructed
    programmaticall y, that contains a lot of sequential scientific data,
    each row being a point in a time-course potentially every minute and
    with data maybe extending over many months. There's a column
    (Date_Time) set as a primary key which contains a datetime stamp (as a
    datetime type) for each row.

    What I'd like to do is to query the datatable for all rows relating to
    say a single day by coding something like (I know this isn't legal
    VB):

    Dim DailyData as datatable = AllData.Select( col("Date_Time" ) where
    datetime start-time AND datetime < end-time)

    I could obviously do something by iterating 'manually' over all the
    rows in AllData, but I was hoping to find a simpler and maybe more
    efficient approach. AllData is just an in-memory datatable so AIUI I
    can't use a standard SQL query on the datatable as I could if it were
    a database. And I'm stuck with VB2005 so I don't believe that I could
    use LINQ, which might make this easy in eg VB2008. So are there any
    other options please?
  • James Hahn

    #2
    Re: How to retrieve multi-row blocks from a datatable?

    I presume that AllData is a System.Data.Dat aTable object, as indicated in
    your example line for the daily data.. You can extract a block of rows from
    the table using criteria such as you have listed with an expression like:

    Dim Daily() as DataRow
    Dim FilterString as String = String.Format(" datetime #{0}# AND datetime <
    #{1}#", DateTime.Parse( start-time), DateTime.Parse( end-time))
    Daily = AllData.Select( FilterString)

    "John Dann" <news@prodata.c o.ukwrote in message
    news:v1leh49b8j lm8a9p3sfvar1j9 43tdjncq1@4ax.c om...
    Is there a concise/efficient way to retrieve blocks of rows from a
    datatable with VB2005?
    >
    I've got a datatable (let's call it AllData), constructed
    programmaticall y, that contains a lot of sequential scientific data,
    each row being a point in a time-course potentially every minute and
    with data maybe extending over many months. There's a column
    (Date_Time) set as a primary key which contains a datetime stamp (as a
    datetime type) for each row.
    >
    What I'd like to do is to query the datatable for all rows relating to
    say a single day by coding something like (I know this isn't legal
    VB):
    >
    Dim DailyData as datatable = AllData.Select( col("Date_Time" ) where
    datetime start-time AND datetime < end-time)
    >
    I could obviously do something by iterating 'manually' over all the
    rows in AllData, but I was hoping to find a simpler and maybe more
    efficient approach. AllData is just an in-memory datatable so AIUI I
    can't use a standard SQL query on the datatable as I could if it were
    a database. And I'm stuck with VB2005 so I don't believe that I could
    use LINQ, which might make this easy in eg VB2008. So are there any
    other options please?

    Comment

    • John Dann

      #3
      Re: How to retrieve multi-row blocks from a datatable?

      On Mon, 10 Nov 2008 11:53:00 +1100, "James Hahn" <jhahn@yahoo.co m>
      wrote:
      >I presume that AllData is a System.Data.Dat aTable object, as indicated in
      >your example line for the daily data.. You can extract a block of rows from
      >the table using criteria such as you have listed with an expression like:
      >
      >Dim Daily() as DataRow
      >Dim FilterString as String = String.Format(" datetime #{0}# AND datetime <
      >#{1}#", DateTime.Parse( start-time), DateTime.Parse( end-time))
      >Daily = AllData.Select( FilterString)
      >
      Many thanks. I'll be able to take a detailed look at this a little
      later in the day. Yes in my example AllData was indeed a standard
      DataTable object.

      Ideally what I'd like to return is another - obviously smaller -
      DataTable. Is there a neat (I'm thinking single line of code) way of
      reassembling that array of datarows (ie Daily() ) back into a
      DataTable? Or do I need to somehow clone the schema from the original
      datatable and instantiate a new empty datatable and then iterate
      through all the rows in Daily() and add each in turn to the new
      datatable?

      Comment

      • John Dann

        #4
        Re: How to retrieve multi-row blocks from a datatable?

        On Mon, 10 Nov 2008 11:53:00 +1100, "James Hahn" <jhahn@yahoo.co m>
        wrote:
        >I presume that AllData is a System.Data.Dat aTable object, as indicated in
        >your example line for the daily data.. You can extract a block of rows from
        >the table using criteria such as you have listed with an expression like:
        >
        >Dim Daily() as DataRow
        >Dim FilterString as String = String.Format(" datetime #{0}# AND datetime <
        >#{1}#", DateTime.Parse( start-time), DateTime.Parse( end-time))
        >Daily = AllData.Select( FilterString)
        >
        Sadly I can't get this to work. In the above FilterString definition
        if I use:

        Dim FilterString as String = String.Format(" Date_Time #{0}# AND
        DateTime ,<#{1}#", DateTime.Parse( "1/5/2008"), DateTime.Parse(
        "13/5/2008"))

        (Date_Time is the column name for my datetime column and I'm working
        with some data from May 2008) then I get:

        FilterString = "Date_Time >#1/5/2008 00:00:00# AND Date_Time
        <#13/5/2008 00:00:00#"

        which seems as expected. But at the line

        Daily = AllData.Select( FilterString)

        a 'FormatExceptio n not handled' error 'String was not recognised as a
        valid DateTime' is thrown.

        It seems like this suggestion is trying to select from a datetime type
        column by searching on a string type, which maybe (?) can't work?

        Is there an error in my code snippett that I haven't spotted? Or is
        there some other way of formatting the filter string that will filter
        on datetime types?

        Comment

        • Armin Zingler

          #5
          Re: How to retrieve multi-row blocks from a datatable?

          "John Dann" <news@prodata.c o.ukschrieb
          Dim FilterString as String = String.Format(" Date_Time #{0}# AND
          DateTime ,<#{1}#", DateTime.Parse( "1/5/2008"), DateTime.Parse(
          "13/5/2008"))
          >
          (Date_Time is the column name for my datetime column and I'm working
          with some data from May 2008) then I get:
          >
          FilterString = "Date_Time >#1/5/2008 00:00:00# AND Date_Time
          <#13/5/2008 00:00:00#"
          You'd better display the value during debugging because this string is not
          the one created by the assignment. In the assignment, you have a "," too
          much between "DateTime" and "<".

          In addition, you can use date literals instead of parsing a string.

          "13/5/2008" dosn't work because there is not 13th month.

          You should also be aware of different date/time formats depending on the
          current locale, so I recommend using a determined format:

          Const DateTimeFormat As String = "\#MM\/dd\/yyyy HH\:mm\:ss\#"

          Dim MinDate = #5/1/2008#
          Dim MaxDate = #5/13/2008#

          Dim FilterString As String = String.Format( _
          "test {0} AND test <{1}", _
          mindate.ToStrin g(DateTimeForma t), _
          maxdate.ToStrin g(DateTimeForma t) _
          )



          Armin

          Comment

          • John Dann

            #6
            Re: How to retrieve multi-row blocks from a datatable?

            On Tue, 11 Nov 2008 16:32:48 +0100, "Armin Zingler"
            <az.nospam@free net.dewrote:
            >
            >You'd better display the value during debugging because this string is not
            >the one created by the assignment. In the assignment, you have a "," too
            >much between "DateTime" and "<".
            Many thanks -that's very useful.

            Sorry I don't have a news client on my VB development PC so I was
            copying manually and obviously introduced an error. Here's the actual
            string:

            Date_Time >#01/05/2008 00:00:00# AND Date_Time <#13/05/2008 00:00:00#

            which looks as intended to me.

            However, the actual mindate and maxdate values (as you've named them)
            are actually pre-existing datetime-type values in my code. If I print
            one of these values in a msgbox it looks like:

            13/05/2008 00:00:00 (UK locale)

            So I've rewritten your example as follows:

            Const DateTimeFormat As String = "dd\/MM\/yyyy HH\:mm\:ss"

            Dim FilterString As String = String.Format(" Date_Time >{0} AND
            Date_Time <{1}", _
            mindate.ToStrin g(DateTimeForma t), maxdate.ToStrin g(DateTimeForma t))


            But the datatable.Selec t operation is giving a SyntaxErrorExce ption
            saying 'Missing operand after '00' operator'. So it looks like I'm
            making progress in that the previous FormatException error has
            vanished. But there's clearly something about format string that's not
            quite right. Unfortunately I can't spot what that is. (NB Code above
            is cut and paste across machines so is definitely exactly as is
            written in the working code - other than line wrap.)

            Comment

            • Armin Zingler

              #7
              Re: How to retrieve multi-row blocks from a datatable?

              "John Dann" <news@prodata.c o.ukschrieb
              Const DateTimeFormat As String = "dd\/MM\/yyyy HH\:mm\:ss"
              The format string I posted was:

              Const DateTimeFormat As String = "\#MM\/dd\/yyyy HH\:mm\:ss\#"



              Armin

              Comment

              • Rich P

                #8
                Re: How to retrieve multi-row blocks from a datatable?

                Hi John,

                I have done what you are trying to do. It is doable, but it is not a
                one liner. Essentially, you need/want to execute some sql operations on
                the fly based on the current rows you are working with. You have 2
                options.

                The 1st option is to go with the Rows retrieved from the
                ds.Table.Select ("StartDate >= '" & SomeStartDate.T oString & "' And
                StartDate <= '" & someEndDate.ToS tring & "'")

                Then loop through this datarow array into a dataTable you create in code
                and populate the datatable. Kinda kludgy but doable.

                The 2nd option is to push the data in your local datatable back to sql
                server to a #tmp table and then query the #tmp table. This gives you a
                little more flexibility. The caveat is that you have to create the #tmp
                table in your code first (there is no escaping having to create a table
                in code first - either a #tmp table or a local dataTable). Here is an
                example:

                ---------------------------------------
                '--da4 is a sqlDataAdapter

                da4.SelectComma nd.CommandText = "If (object_id('tem pdb..#tmp1') is not
                null) drop table #tmp1"
                da4.SelectComma nd.ExecuteNonQu ery()

                '--create #tmp1 in TempDB
                da4.SelectComma nd.CommandText = "Create Table #tmp1(FirstDate datetime,
                ListNo varchar(2))"
                da4.SelectComma nd.ExecuteNonQu ery()

                '--now copy the #tmp1 structure to memory for app usage
                da4.SelectComma nd.CommandText = "Select * From #tmp1"
                da4.Fill(dsFL, "tmpLocal")

                da4.InsertComma nd.CommandText = "Insert Into #tmp1(FirstDate , ListNo)
                Select @FirstDate, @ListNo"

                da4.InsertComma nd.Parameters.A dd("@FirstDate" , SqlDbType.DateT ime, 8,
                "FirstDate" )
                da4.InsertComma nd.Parameters.A dd("@ListNo", SqlDbType.VarCh ar, 2,
                "ListNo")

                Dim reader As DataTableReader =
                dataset1.YourLo calDataTable.Cr eateDataReader

                '--set up the data push here
                dataset1.Tables ("tmpLocal").Lo ad(reader, LoadOption.Upse rt)

                '--This is where you push the data
                '--from yourLocalTable to #tmp1
                da4.Update(dsFL , "tmpLocal")

                '--now you can use tSql on #tmp1
                da4.SelectComma nd.CommandText = "Select * From #tmp1 Where Some
                Condition"
                da4.Fill(datase t1, "tblResult" )

                Datagridview1.D ataSource = dataset1.Tables ("tblResult" )

                Rich

                *** Sent via Developersdex http://www.developersdex.com ***

                Comment

                • John Dann

                  #9
                  Re: How to retrieve multi-row blocks from a datatable?

                  On Tue, 11 Nov 2008 18:08:08 +0100, "Armin Zingler"
                  <az.nospam@free net.dewrote:
                  >"John Dann" <news@prodata.c o.ukschrieb
                  >Const DateTimeFormat As String = "dd\/MM\/yyyy HH\:mm\:ss"
                  >
                  >The format string I posted was:
                  >
                  >Const DateTimeFormat As String = "\#MM\/dd\/yyyy HH\:mm\:ss\#"
                  >
                  Yes, I know. The thinking was that in your example mindate was
                  explicitly bounded by # characters. In my code, mindate is a
                  pre-assigned datetime type that, so far as I know, has no bounding #
                  characters, so I took them out. If I use the format string almost
                  exactly as you posted:

                  Const DateTimeFormat As String = "\#dd\/MM\/yyyy HH\:mm\:ss\#"

                  (pasted from my code) then I revert to the original 'string was not
                  recognised as a valid datetime' error. I've obviously interchanged dd
                  and MM compared to your example, but that's how datetime values seem
                  to appear to my system.

                  Maybe I should be adding bounding # characters to the formatted
                  values? ie instead of:

                  mindate.ToStrin g(DateTimeForma t)

                  it should be

                  "#" & mindate.ToStrin g(DateTimeForma t) & "#"

                  Sorry there's obviously something that I don't understand about the
                  exact usage and syntax of datetime values. But if you can spot any
                  further errors that I'm committing then I'd be most grateful.

                  Comment

                  • John Dann

                    #10
                    Re: How to retrieve multi-row blocks from a datatable?

                    On Tue, 11 Nov 2008 09:28:45 -0800, Rich P <rpng123@aol.co mwrote:
                    >The 1st option is to go with the Rows retrieved from the
                    >ds.Table.Selec t("StartDate >= '" & SomeStartDate.T oString & "' And
                    >StartDate <= '" & someEndDate.ToS tring & "'")
                    >
                    >Then loop through this datarow array into a dataTable you create in code
                    >and populate the datatable. Kinda kludgy but doable.
                    >
                    This is what I'm currently trying to do, but seeing a problem with. I
                    was hoping I could do:

                    Dim Daily() As DataRow
                    Daily = MonthlyRawDT.Se lect(FilterStri ng) ' FilterString set elsewhere

                    Dim DailyRawDT As DataTable = MonthlyRawDT.Cl one()
                    For Each dr As DataRow In Daily
                    DailyRawDT.Rows .Add(dr)
                    Next

                    So:

                    MonthlyRawDT is my parent datatable from which I'm trying to extract a
                    subset of rows.

                    Daily() is the array of datarows populated by the .Select method.

                    Then I was thinking that I needed to instantiate a new datatable with
                    the same schema as the original parent datatable and iterate through
                    the datarows array adding one row at a time to the new datatable. But
                    I get the error that dr already belongs to another datatable.

                    Have I miscoded this (been a long day today!) or do I need to iterate
                    through each row item by item. That would be kludgy!

                    I guess VB2008 and LINQ really might make this exercise simpler?

                    Comment

                    • Rich P

                      #11
                      Re: How to retrieve multi-row blocks from a datatable?

                      do a console.writeli ne (or debug.print) on your date vars to see what
                      kind of data value your are passing in to

                      ds.table.Select ("StartDate = '"...

                      And don't forget that .Select(...) is the Where clause in a tsql
                      statement and uses the same syntax - you have to delimit your dates with
                      single quotes .Select("StartD ate = '" & someDateVar.ToS tring & "'")

                      So the DateVar needs to be a string to fit into the Where Clause of
                      ..Select("Start Date = '" & DateVar.ToStrin g & "'")

                      The DataRow Array is OK if you only have a few rows to filter. But if
                      you have lots of rows (more than 50 say)you will be better off pushing
                      your data back to the server to a #tmp table and then use regular tsql
                      on the #tmp table. It may seem kludgy at first, but way more flexible
                      than looping through an array of datarows.


                      Rich

                      *** Sent via Developersdex http://www.developersdex.com ***

                      Comment

                      • James Hahn

                        #12
                        Re: How to retrieve multi-row blocks from a datatable?

                        You can copy the datarows into a new table that has been created with the
                        same structure as the original. .ImportRow is probably the easiest way to do
                        this. See, for instance:
                        Blogger ist ein Veröffentlichungs-Tool von Google, mit dem du ganz einfach deine Gedanken der Welt mitteilen kannst. Mit Blogger kannst du problemlos Texte, Fotos und Videos in deinem persönlichen Blog oder deinem Team-Blog veröffentlichen.


                        "John Dann" <news@prodata.c o.ukwrote in message
                        news:vlhjh49rb3 ed2e2b70efst7k0 itm8jb2pb@4ax.c om...
                        On Tue, 11 Nov 2008 09:28:45 -0800, Rich P <rpng123@aol.co mwrote:
                        snip <
                        >
                        This is what I'm currently trying to do, but seeing a problem with. I
                        was hoping I could do:
                        >
                        Dim Daily() As DataRow
                        Daily = MonthlyRawDT.Se lect(FilterStri ng) ' FilterString set elsewhere
                        >
                        Dim DailyRawDT As DataTable = MonthlyRawDT.Cl one()
                        For Each dr As DataRow In Daily
                        DailyRawDT.Rows .Add(dr)
                        Next
                        >
                        So:
                        >
                        MonthlyRawDT is my parent datatable from which I'm trying to extract a
                        subset of rows.
                        >
                        Daily() is the array of datarows populated by the .Select method.
                        >
                        Then I was thinking that I needed to instantiate a new datatable with
                        the same schema as the original parent datatable and iterate through
                        the datarows array adding one row at a time to the new datatable. But
                        I get the error that dr already belongs to another datatable.
                        >
                        Have I miscoded this (been a long day today!) or do I need to iterate
                        through each row item by item. That would be kludgy!
                        >
                        I guess VB2008 and LINQ really might make this exercise simpler?

                        Comment

                        Working...