简体   繁体   中英

How to Count Values in Access Database using Visual Studio VB.NET

I have an access database that stores data in a table (called DataCollection) that is logged by a Visual Studio program. I have been struggling to find a solution to how to count the number records that contain specific values in specific columns.

For example, in my database, there are two columns. One column is titled "M/Y OF LOG" and it returns dates formatted like this "1/1/2021". The other column is titled "MISSED PART", and it can return only two values, "Missed Part" or "NEATOL". Ideally, I would like to count, using Visual Studio, the number of times "Missed Part" occurs in a certain month.

Does anyone have any ideas on how the code for this may look, or if counting like this is even possible?

My connection string:

connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Database1.accdb"

Preview of my Access database formatting:

You will see there are many more columns than mentioned. Please ignore any columns other than "M/Y of Log" and "Missed Part"

在此处输入图像描述

I have these variables in my code. They will be the variables that hole the return values from the database, used as y values in graphs to display the data:

Private Function CountMissedParts() Handles MyBase.Load

    Dim sql = $"SELECT COUNT(*)
        FROM DataCollection
        WHERE [MISSED PART] = 'Missed Part'
        AND [M/Y OF LOG] = @MY_OF_LOG;"
    Dim JANmyOfLog = #1/1/2021#
    Dim FEBmyOfLog = #2/1/2021#
    Dim MARmyOfLog = #3/1/2021#
    Dim APRmyOfLog = #4/1/2021#
    Dim MAYmyOfLog = #5/1/2021#
    Dim JUNmyOfLog = #6/1/2021#
    Dim JULmyOfLog = #7/1/2021#
    Dim AUGmyOfLog = #8/1/2021#
    Dim SEPmyOfLog = #9/1/2021#
    Dim OCTmyOfLog = #10/1/2021#
    Dim NOVmyOfLog = #11/1/2021#
    Dim DECmyOfLog = #12/1/2021#
    Dim count As Integer
    Dim JanuaryMP As Double
    Dim FebruaryMP As Double
    Dim MarchMP As Double
    Dim AprilMP As Double
    Dim MayMP As Double
    Dim JuneMP As Double
    Dim JulyMP As Double
    Dim AugustMP As Double
    Dim SeptemberMP As Double
    Dim OctoberMP As Double
    Dim NovemberMP As Double
    Dim DecemberMP As Double

    Using connection As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Database1.accdb"),
            command As New OleDbCommand(sql, connection)
        JanuaryMP = command.Parameters.Add("@MY_OF_LOG", OleDbType.Date).Value = JANmyOfLog
        FebruaryMP = command.Parameters.Add("@MY_OF_LOG", OleDbType.Date).Value = FEBmyOfLog
        MarchMP = command.Parameters.Add("@MY_OF_LOG", OleDbType.Date).Value = MARmyOfLog
        AprilMP = command.Parameters.Add("@MY_OF_LOG", OleDbType.Date).Value = APRmyOfLog
        MayMP = command.Parameters.Add("@MY_OF_LOG", OleDbType.Date).Value = MAYmyOfLog
        JuneMP = command.Parameters.Add("@MY_OF_LOG", OleDbType.Date).Value = JUNmyOfLog
        JulyMP = command.Parameters.Add("@MY_OF_LOG", OleDbType.Date).Value = JULmyOfLog
        AugustMP = command.Parameters.Add("@MY_OF_LOG", OleDbType.Date).Value = AUGmyOfLog
        SeptemberMP = command.Parameters.Add("@MY_OF_LOG", OleDbType.Date).Value = SEPmyOfLog
        OctoberMP = command.Parameters.Add("@MY_OF_LOG", OleDbType.Date).Value = OCTmyOfLog
        NovemberMP = command.Parameters.Add("@MY_OF_LOG", OleDbType.Date).Value = NOVmyOfLog
        DecemberMP = command.Parameters.Add("@MY_OF_LOG", OleDbType.Date).Value = DECmyOfLog
        connection.Open()
        count = command.ExecuteScalar()




        ' set 0,0
        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(0, 0)
        ' other points
        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(1, JanuaryMP)

        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(2, FebruaryMP)

        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(3, MarchMP)

        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(4, AprilMP)

        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(5, MayMP)

        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(6, JuneMP)

        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(7, JulyMP)

        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(8, AugustMP)

        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(9, SeptemberMP)

        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(10, OctoberMP)

        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(11, NovemberMP)

        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(12, DecemberMP)

    End Using
    NotInEpicorCHRT.ChartAreas(0).AxisX.Minimum = 0.0
    NotInEpicorCHRT.ChartAreas(0).AxisX.Maximum = 12
    NotInEpicorCHRT.ChartAreas(0).AxisX.Interval = 1
    NotInEpicorCHRT.ChartAreas(0).AxisY.Minimum = 0.0
    NotInEpicorCHRT.ChartAreas(0).AxisY.Maximum = 45
    NotInEpicorCHRT.ChartAreas(0).AxisY.Interval = 5
End Function
Dim sql = $"SELECT COUNT(*)
            FROM DataCollection
            WHERE [MISSED PART] = 'Missed Part'
            AND [M/Y OF LOG] = @MY_OF_LOG"
Dim myOfLog = #1/01/2021#
Dim count As Integer

Using connection As New OleDbConnection("connection string here"),
      command As New OleDbCommand(sql, connection)
    command.Parameters.Add("@MY_OF_LOG", OleDbType.Date).Value = myOfLog
    connection.Open()
    count = CInt(command.ExecuteScalar())
End Using

That example uses a hard-coded date but you can get the date value from anywhere you like. A Date is a Date .

There is no need to define variable for each month, you can use loop instead.

Check the following code:

    Dim count As Integer
    Dim lst As List(Of Double) = New List(Of Double)

    Dim sql = $"SELECT COUNT(*) FROM DataCollection WHERE [MISSED PART] = 'Missed Part' AND [M/Y OF LOG] = @MY_OF_LOG;"

    Using connection As New OleDbConnection("your connection String"),
            command As New OleDbCommand(sql, connection)
        connection.Open()

        For i As Integer = 1 To 12
            command.Parameters.Clear()
            Dim dtime = New DateTime(2021, i, 1).ToString("MM/dd/yyyy")
            command.Parameters.AddWithValue("@MY_OF_LOG", dtime)
            count = command.ExecuteScalar()
            lst.Add(count)
        Next

        NotInEpicorCHRT.Series("Missed Part").Points.AddXY(0, 0)
        For j As Integer = 1 To lst.Count
            NotInEpicorCHRT.Series("Missed Part").Points.AddXY(j, lst(j - 1))
        Next

    End Using
    NotInEpicorCHRT.ChartAreas(0).AxisX.Minimum = 0.0
    NotInEpicorCHRT.ChartAreas(0).AxisX.Maximum = 12
    NotInEpicorCHRT.ChartAreas(0).AxisX.Interval = 1
    NotInEpicorCHRT.ChartAreas(0).AxisY.Minimum = 0.0
    NotInEpicorCHRT.ChartAreas(0).AxisY.Maximum = 45
    NotInEpicorCHRT.ChartAreas(0).AxisY.Interval = 5

Well, I assume that the date column is a in fact a actual date column. That way, your display of the date does NOT matter. As a general rule, all dates are stored in a internal format - you don't care about the external.

So, all we REALLY need is the month, and year you want.

So, build a form with two text boxes. One text box has year, the other the month.

Say like this:

在此处输入图像描述

So, this code would prompt you for the year, then the month, and then spit out the results.

the button code can be this, and it will give a total for both Missed and NeatOL

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim strSQL As String

    strSQL = "SELECT abs(SUM([Missed Part] = 'Missed Part')) As MissPCount " &
             "abs(SUM([Missed Part] = 'NEATOL')) As MissNCount " &
             "FROM DataCollection WHERE Month([M/Y OF LOG]) = @Month " &
             "AND Year([M/Y OF LOG]) = @Year"

    Using cmdSQL As New OleDbCommand(strSQL,
            New OleDbConnection(My.Settings.TestDB))

        cmdSQL.Parameters.Add("@Month", OleDbType.Integer).Value = txtMonth.Text
        cmdSQL.Parameters.Add("@Year", OleDbType.Integer).Value = txtYear.Text

        cmdSQL.Connection.Open()
        Dim rstTable As New DataTable

        rstTable.Load(cmdSQL.ExecuteReader)

        ' display the reuslts in the two text boxes.
        With rstTable.Rows(0)

            txtNeatCount.Text = .Item("MissNCount")
            txtPartCount.Text = .Item("MissPCount")

        End With

    End Using

End Sub

Edit:

As a follow up? It looks like you have a single column that is ALWAYS set to the 1st of the month. Give this, and that I used month() and year() functions? Well, using month() and year() is great for things like say who has a birthday this month, ( we can use month() and day() to extract the month, day and ignore the year.

HOWEVER, we should STILL include a valid date range. The reason is of course "indexing" or the so called term "sargable". The above query as written can't use indexing for the results. Thus for a large table, the posted query will run quite slow.

A better (and much faster) performing SQL query would be this, assuming there is a index on the MY/Y column. Thus, I suggest this solution:

    strSQL = "SELECT abs(SUM([Missed Part] = 'Missed Part')) As MissPCount " &
             "abs(SUM([Missed Part] = 'NEATOL' As MissNCount " &
             "FROM DataCollection WHERE [M/Y OF LOG] = @MyDate "

    Dim dtMyDate As Date = DateSerial(txtYear.Text, txtMonth.Text, 1)

    Using cmdSQL As New OleDbCommand(strSQL,
            New OleDbConnection(My.Settings.TestDB))

        cmdSQL.Parameters.Add("@MyDate", OleDbType.DBDate).Value = dtMyDate

        cmdSQL.Connection.Open()
etc. etc. etc. etc.

I think the following code will get you the data you need. Ask another question if you need the data.table columns translated to the chart.

Private Sub OPCode()
    Dim sql = $"SELECT [M/Y OF LOG], COUNT([Missed Part]) As Total
                FROM [Data Collection]
                WHERE [MISSED PART] = 'MISSED PART'
                GROUP BY [M/Y OF LOG] 
                ORDER BY [M/Y OF LOG];"
    Dim dt As New DataTable
    Using cn As New OleDbConnection(My.Settings.DataCollection),
            cmd As New OleDbCommand(sql, cn)
        cn.Open()
        dt.Load(cmd.ExecuteReader)
    End Using
    DataGridView1.DataSource = dt
End Sub

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM