简体   繁体   中英

Trouble with SELECT WHERE NOT IS/EXISTS Subquery (VB.NET, Access)

Need some help with an issue I'm having. This is the code:

Private Sub dtpStartDate_ValueChanged(sender As Object, e As EventArgs) Handles dtpStartDate.ValueChanged
    startDateChanged = 1

    If endDateChanged = 1 Then
        cbLocation.Enabled = True
        cbLocation.Items.Clear()
        cbLocation.Items.Add(New ListViewItem(""))
        Dim unbookedLocationsSQL As String = "SELECT locationID FROM Locations WHERE NOT EXISTS (Select LocationID FROM Bookings WHERE @startDate <= bookingEndDate AND bookingStartDate <= @endDate)"
        Dim unbookedLocationsCommand = New OleDbCommand(unbookedLocationsSQL, globalVariables.objConnection)
        Dim unbookedLocationsAdapter As New OleDbDataAdapter(unbookedLocationsSQL, globalVariables.objConnection)
        Dim unbookedLocationsDataSet As New DataSet

        unbookedLocationsCommand.Parameters.AddWithValue("startDate", dtpStartDate.Value)
        unbookedLocationsCommand.Parameters.AddWithValue("endDate", dtpEndDate.Value)

        unbookedLocationsAdapter.Fill(unbookedLocationsDataSet, "Locations")

        With cbLocation
            .DataSource = unbookedLocationsDataSet.Tables("Locations")
            .DisplayMember = "locationID"
            .ValueMember = "locationID"
        End With
    End If
End Sub

First things first, if you change the sql statement to "SELECT * from locations" the combo box just displayed all of locations.

What I am trying to achieve is this; when someone changes both date time pickers, the combo box is enabled and populated with a list of locations that aren't booked between those two dates, which is determined by the bookings table. I know the SQL statement is wrong. I've tried various combinations of things and tried isolating bit and pieces but I can't get any subquery to do what I want.

Any help would be appreciated.

I think something is wrong here

WHERE @startDate <= bookingEndDate AND bookingStartDate <= @endDate

try changing it to

WHERE bookingStartDate >= @startDate AND bookingEndDate <= @endDate

also put in mind to put ".Date" in your parameters..

unbookedLocationsCommand.Parameters.AddWithValue("startDate", dtpStartDate.Value.Date)

If I understood correctly, each entry of the Bookings table reflects one booking even for certain location. In this case, you want:

WHERE @startDate >= bookingEndDate OR bookingStartDate >= @endDate

instead of

WHERE @startDate <= bookingEndDate AND bookingStartDate <= @endDate

Also, if Bookings table can have multiple entries for the same location, this will not work: you have to make sure NONE of the bookings at the location overlaps with the input dates.

And since I cannot comment (yet) on other answers, I will note here that the answer by Codemunkeee is wrong - using his query ( WHERE bookingStartDate >= @startDate AND bookingEndDate <= @endDate ) you will get exactly those locations where booking overlaps with the requested dates, so it's opposite to what you want. Unless, of course, I misunderstood something about the Bookings table.

Here is the code now it's working:

 Private Sub dtpStartDate_ValueChanged(sender As Object, e As EventArgs) Handles dtpStartDate.ValueChanged
        startDateChanged = 1

        If endDateChanged = 1 Then
            cbLocation.Enabled = True
            Me.Refresh()
            cbLocation.Items.Add(New ListViewItem(""))
            Dim unbookedLocationsSQL As String = "SELECT * FROM Locations WHERE LocationID NOT IN (SELECT LocationID FROM Bookings WHERE bookingEndDate >= @startDate AND bookingStartDate <= @endDate)"
            Dim unbookedLocationsCommand = New OleDbCommand(unbookedLocationsSQL, globalVariables.objConnection)
            Dim unbookedLocationsAdapter As New OleDbDataAdapter(unbookedLocationsSQL, globalVariables.objConnection)
            Dim unbookedLocationsDataSet As New DataSet

            unbookedLocationsCommand.Parameters.AddWithValue("startDate", dtpStartDate.Value)
            unbookedLocationsCommand.Parameters.AddWithValue("endDate", dtpEndDate.Value)
            unbookedLocationsAdapter.SelectCommand = unbookedLocationsCommand
            unbookedLocationsAdapter.Fill(unbookedLocationsDataSet, "Locations")

            With cbLocation
                .DataSource = unbookedLocationsDataSet.Tables("Locations")
                .DisplayMember = "LocationName"
                .ValueMember = "LocationID"
            End With
        End If
    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