diff --git a/pydov/util/query.py b/pydov/util/query.py
index f7cd9a2..dae02b5 100644
--- a/pydov/util/query.py
+++ b/pydov/util/query.py
@@ -7,7 +7,7 @@ from owslib.fes import (
 )
 
 
-class PropertyInList(Or):
+class PropertyInList(object):
     """Filter expression to test whether a given property has one of the
     values from a list.
 
@@ -33,19 +33,30 @@ class PropertyInList(Or):
         Raises
         ------
         ValueError
-            If the given list does not contain at least two distinct items.
+            If the given list does not contain at least a single item.
 
         """
         if not isinstance(lst, list) and not isinstance(lst, set):
             raise ValueError('list should be of type "list" or "set"')
 
-        if len(set(lst)) < 2:
-            raise ValueError('list should contain at least two different '
-                             'elements.')
+        if len(set(lst)) < 1:
+            raise ValueError('list should contain at least a single item')
+        elif len(set(lst)) == 1:
+            self.query = PropertyIsEqualTo(propertyname, set(lst).pop())
+        else:
+            self.query = Or(
+                [PropertyIsEqualTo(propertyname, i) for i in set(lst)])
 
-        super(PropertyInList, self).__init__(
-            [PropertyIsEqualTo(propertyname, i) for i in set(lst)]
-        )
+    def toXML(self):
+        """Return the XML representation of the PropertyInList query.
+
+        Returns
+        -------
+        xml : etree.ElementTree
+            XML representation of the PropertyInList
+
+        """
+        return self.query.toXML()
 
 
 class Join(PropertyInList):
@@ -83,9 +94,8 @@ class Join(PropertyInList):
             If `using` is None and the `on` column is not present in the
             dataframe.
 
-            If the dataframe does not contain at least two different values
-            in the `using` column. A Join is probably overkill here,
-            use PropertyIsEqualTo instead.
+            If the dataframe does not contain at least a single non-null value
+            in the `using` column.
 
         """
         if using is None:
@@ -98,8 +108,8 @@ class Join(PropertyInList):
 
         value_list = list(dataframe[using].dropna().unique())
 
-        if len(set(value_list)) < 2:
-            raise ValueError("dataframe should contain at least two "
-                             "different values in column '{}'.".format(using))
+        if len(set(value_list)) < 1:
+            raise ValueError("dataframe should contain at least a single "
+                             "value in column '{}'.".format(using))
 
         super(Join, self).__init__(on, value_list)

Support Join with a dataframe containing a single element too
<!-- You can ask questions about the DOV webservices or about the `pydov` package. If you have a question about the `pydov` Python package, please use following template. -->

* PyDOV version: master
* Python version: 3.6
* Operating System: Windows 10

### Description

When you use Join with a dataframe with only one (unique) element, you get an error. It would be nice if the Join would work with a dataframe containing only a single element too.

### What I Did

```
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-41-455ef57ac5bc> in <module>()
      4 gwl = GrondwaterLocatieSearch()
      5 
----> 6 gwl.search(Join(df, 'pkey_grondwaterlocatie'))

c:\projecten\pydov\pydov_git\pydov\util\query.py in __init__(self, dataframe, on, using)
    101         if len(set(value_list)) < 2:
    102             raise ValueError("dataframe should contain at least two "
--> 103                              "different values in column '{}'.".format(using))
    104 
    105         super(Join, self).__init__(on, value_list)

ValueError: dataframe should contain at least two different values in column 'pkey_grondwaterlocatie'.
```

diff --git a/tests/test_util_query.py b/tests/test_util_query.py
index c14c1ed..750acc3 100644
--- a/tests/test_util_query.py
+++ b/tests/test_util_query.py
@@ -1,5 +1,6 @@
 """Module grouping tests for the pydov.util.query module."""
 import pandas as pd
+import numpy as np
 import pytest
 
 from pydov.util.query import (
@@ -67,26 +68,63 @@ class TestPropertyInList(object):
 
         assert len(l_output) == 0
 
-    def test_tooshort(self):
+    def test_list_single(self):
         """Test the PropertyInList expression with a list containing
         a single item.
 
-        Test whether a ValueError is raised.
+        Test whether the generated query is correct and does contain only a
+        single PropertyIsEqualTo.
 
         """
-        with pytest.raises(ValueError):
-            l = ['a']
-            PropertyInList('methode', l)
+        l = ['a']
+
+        query = PropertyInList('methode', l)
+        xml = query.toXML()
+
+        assert xml.tag == '{http://www.opengis.net/ogc}PropertyIsEqualTo'
+
+        propertyname = xml.find('./{http://www.opengis.net/ogc}PropertyName')
+        assert propertyname.text == 'methode'
 
-    def test_tooshort_duplicate(self):
+        literal = xml.find('./{http://www.opengis.net/ogc}Literal')
+        assert literal.text in l
+
+        l.remove(literal.text)
+        assert len(l) == 0
+
+    def test_list_single_duplicate(self):
         """Test the PropertyInList expression with a list containing
-        a two identical items.
+        a single duplicated item.
+
+        Test whether the generated query is correct and does contain only a
+        single PropertyIsEqualTo.
+
+        """
+        l = ['a', 'a']
+        l_output = ['a']
+
+        query = PropertyInList('methode', l)
+        xml = query.toXML()
+
+        assert xml.tag == '{http://www.opengis.net/ogc}PropertyIsEqualTo'
+
+        propertyname = xml.find('./{http://www.opengis.net/ogc}PropertyName')
+        assert propertyname.text == 'methode'
+
+        literal = xml.find('./{http://www.opengis.net/ogc}Literal')
+        assert literal.text in l_output
+
+        l_output.remove(literal.text)
+        assert len(l_output) == 0
+
+    def test_emptylist(self):
+        """Test the PropertyInList expression with an empty list.
 
         Test whether a ValueError is raised.
 
         """
         with pytest.raises(ValueError):
-            l = ['a', 'a']
+            l = []
             PropertyInList('methode', l)
 
     def test_nolist(self):
@@ -194,38 +232,77 @@ class TestJoin(object):
 
             Join(df, 'pkey_sondering')
 
-    def test_tooshort(self):
+    def test_single(self):
         """Test the Join expression with a dataframe containing a single row.
 
-        Test whether a ValueError is raised.
+        Test whether the generated query is correct and does contain only a
+        single PropertyIsEqualTo.
 
         """
-        with pytest.raises(ValueError):
-            l = ['https://www.dov.vlaanderen.be/data/boring/1986-068853']
+        l = ['https://www.dov.vlaanderen.be/data/boring/1986-068853']
 
-            df = pd.DataFrame({
-                'pkey_boring': pd.Series(l),
-                'diepte_tot_m': pd.Series([10])
-            })
+        df = pd.DataFrame({
+            'pkey_boring': pd.Series(l),
+            'diepte_tot_m': pd.Series([10])
+        })
 
-            Join(df, 'pkey_boring')
+        query = Join(df, 'pkey_boring')
+        xml = query.toXML()
+
+        assert xml.tag == '{http://www.opengis.net/ogc}PropertyIsEqualTo'
+
+        propertyname = xml.find('./{http://www.opengis.net/ogc}PropertyName')
+        assert propertyname.text == 'pkey_boring'
 
-    def test_tooshort_duplicate(self):
+        literal = xml.find('./{http://www.opengis.net/ogc}Literal')
+        assert literal.text in l
+
+        l.remove(literal.text)
+        assert len(l) == 0
+
+    def test_single_duplicate(self):
         """Test the Join expression with a dataframe containing two
         identical keys.
 
-        Test whether a ValueError is raised.
+        Test whether the generated query is correct and does contain only a
+        single PropertyIsEqualTo.
 
         """
-        with pytest.raises(ValueError):
-            l = ['https://www.dov.vlaanderen.be/data/boring/1986-068853',
-                 'https://www.dov.vlaanderen.be/data/boring/1986-068853']
+        l = ['https://www.dov.vlaanderen.be/data/boring/1986-068853',
+             'https://www.dov.vlaanderen.be/data/boring/1986-068853']
+        l_output = ['https://www.dov.vlaanderen.be/data/boring/1986-068853']
 
-            df = pd.DataFrame({
-                'pkey_boring': pd.Series(l),
-                'diepte_tot_m': pd.Series([10, 20])
-            })
+        df = pd.DataFrame({
+            'pkey_boring': pd.Series(l),
+            'diepte_tot_m': pd.Series([10, 20])
+        })
+
+        query = Join(df, 'pkey_boring')
+        xml = query.toXML()
+
+        assert xml.tag == '{http://www.opengis.net/ogc}PropertyIsEqualTo'
+
+        propertyname = xml.find('./{http://www.opengis.net/ogc}PropertyName')
+        assert propertyname.text == 'pkey_boring'
+
+        literal = xml.find('./{http://www.opengis.net/ogc}Literal')
+        assert literal.text in l_output
+
+        l_output.remove(literal.text)
+        assert len(l_output) == 0
+
+    def test_empty(self):
+        """Test the Join expression with an empty dataframe.
+
+        Test whether a ValueError is raised
+
+        """
+        df = pd.DataFrame({
+            'pkey_boring': [np.nan, np.nan],
+            'diepte_tot_m': pd.Series([10, 20])
+        })
 
+        with pytest.raises(ValueError):
             Join(df, 'pkey_boring')
 
     def test_on(self):

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
certifi==2021.5.30
charset-normalizer==2.0.12
dataclasses==0.8
idna==3.10
importlib-metadata==4.8.3
iniconfig==1.1.1
lxml==5.3.1
numpy==1.19.5
OWSLib==0.31.0
packaging==21.3
pandas==1.1.5
pluggy==1.0.0
py==1.11.0
-e git+https://github.com/DOV-Vlaanderen/pydov.git@325fad8fd06d5b2077366869c2f5a0017d59941b#egg=pydov
pyparsing==3.1.4
pytest==7.0.1
python-dateutil==2.9.0.post0
pytz==2025.2
PyYAML==6.0.1
requests==2.27.1
six==1.17.0
tomli==1.2.3
typing_extensions==4.1.1
urllib3==1.26.20
zipp==3.6.0

name: pydov
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - charset-normalizer==2.0.12
      - dataclasses==0.8
      - idna==3.10
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - lxml==5.3.1
      - numpy==1.19.5
      - owslib==0.31.0
      - packaging==21.3
      - pandas==1.1.5
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - pyyaml==6.0.1
      - requests==2.27.1
      - six==1.17.0
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - zipp==3.6.0
prefix: /opt/conda/envs/pydov

tests/test_util_query.py::TestPropertyInList::test_list_single tests/test_util_query.py::TestPropertyInList::test_list_single_duplicate tests/test_util_query.py::TestJoin::test_single tests/test_util_query.py::TestJoin::test_single_duplicate
tests/test_util_query.py::TestPropertyInList::test tests/test_util_query.py::TestPropertyInList::test_duplicate tests/test_util_query.py::TestPropertyInList::test_emptylist tests/test_util_query.py::TestPropertyInList::test_nolist tests/test_util_query.py::TestJoin::test tests/test_util_query.py::TestJoin::test_duplicate tests/test_util_query.py::TestJoin::test_wrongcolumn tests/test_util_query.py::TestJoin::test_empty tests/test_util_query.py::TestJoin::test_on tests/test_util_query.py::TestJoin::test_using
pydov/util/query.py
pydov/util/query.py