diff --git a/core/lib/Drupal/Core/Entity/Query/QueryInterface.php b/core/lib/Drupal/Core/Entity/Query/QueryInterface.php
index e673db1..b33e9ab 100644
--- a/core/lib/Drupal/Core/Entity/Query/QueryInterface.php
+++ b/core/lib/Drupal/Core/Entity/Query/QueryInterface.php
@@ -15,6 +15,11 @@
 interface QueryInterface extends AlterableInterface {
 
   /**
+   * A property that represents delta used in entity query conditions.
+   */
+  const DELTA = '*delta';
+
+  /**
    * Gets the ID of the entity type for this query.
    *
    * @return string
@@ -46,6 +51,17 @@ public function getEntityTypeId();
    *   "tags" "is the same as "tags.value" as value is the default column.
    *   If two or more conditions have the same field names they apply to the
    *   same delta within that field.
+   *   It is also possible to add the numeric delta value between the field
+   *   name and the column name, for example tags.5.value.
+   *   Finally, it's possible to create a condition on delta itself by using a
+   *   ? as a wildcard. For example, ->condition('tags.?', 5) will find only
+   *   entities which have at least six tags. Also, tags.? within a condition
+   *   group means a specific delta so
+   * @code
+   *   ->condition('tags.?', 0, '>'))
+   *   ->condition('tags.?.value', 'foo'))
+   * @endcode
+   *   will only find the "foo" tag if it is not the first tag.
    * @param $value
    *   The value for $field. In most cases, this is a scalar and it's treated as
    *   case-insensitive. For more complex operators, it is an array. The meaning
diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
index f3835ff..73712b2 100644
--- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
+++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
@@ -4,6 +4,7 @@
 
 use Drupal\Core\Database\Query\SelectInterface;
 use Drupal\Core\Entity\Query\QueryException;
+use Drupal\Core\Entity\Query\QueryInterface;
 use Drupal\Core\Entity\Sql\SqlEntityStorageInterface;
 
 /**
@@ -110,11 +111,35 @@ public function addField($field, $type, $langcode) {
 
       // Check whether this field is stored in a dedicated table.
       if ($field_storage && $table_mapping->requiresDedicatedTableStorage($field_storage)) {
+        $delta = NULL;
         // Find the field column.
         $column = $field_storage->getMainPropertyName();
 
         if ($key < $count) {
           $next = $specifiers[$key + 1];
+          // Is this a delta value?
+          if (is_numeric($next)) {
+            $delta = $next;
+            $index_prefix .= ".$delta";
+            // Do not process it again.
+            $key++;
+            $next = $specifiers[$key + 1];
+          }
+          // Is this a delta wildcard?
+          elseif ($next == '?') {
+            $index_prefix .= '.?';
+            // Do not process it again.
+            $key++;
+            // If there are yet specifiers to work with then continue
+            // processing. If this is the last specifier then use the delta
+            // wildcard as column name.
+            if ($key < $count) {
+              $next = $specifiers[$key + 1];
+            }
+            else {
+              $column = QueryInterface::DELTA;
+            }
+          }
           // Is this a field column?
           $columns = $field_storage->getColumns();
           if (isset($columns[$next]) || in_array($next, $table_mapping->getReservedColumns())) {
@@ -138,7 +163,7 @@ public function addField($field, $type, $langcode) {
             $next_index_prefix = "$relationship_specifier.$column";
           }
         }
-        $table = $this->ensureFieldTable($index_prefix, $field_storage, $type, $langcode, $base_table, $entity_id_field, $field_id_field);
+        $table = $this->ensureFieldTable($index_prefix, $field_storage, $type, $langcode, $base_table, $entity_id_field, $field_id_field, $delta);
         $sql_column = $table_mapping->getFieldColumnName($field_storage, $column);
         $property_definitions = $field_storage->getPropertyDefinitions();
         if (isset($property_definitions[$column])) {
@@ -164,6 +189,24 @@ public function addField($field, $type, $langcode) {
         // next one is a column of this field.
         if ($key < $count) {
           $next = $specifiers[$key + 1];
+          // Is this a delta wildcard?
+          if ($next == '?') {
+            $key++;
+            if ($key < $count) {
+              $next = $specifiers[$key + 1];
+            }
+            else {
+              return 0;
+            }
+          }
+          // Is this a delta value?
+          if (is_numeric($next)) {
+            if ($next > 0) {
+              $this->sqlQuery->condition('1 <> 1');
+            }
+            $key++;
+            $next = $specifiers[$key + 1];
+          }
           // Is this a field column?
           $columns = $field_storage->getColumns();
           if (isset($columns[$next]) || in_array($next, $table_mapping->getReservedColumns())) {
@@ -255,7 +298,7 @@ protected function ensureEntityTable($index_prefix, $property, $type, $langcode,
    * @return string
    * @throws \Drupal\Core\Entity\Query\QueryException
    */
-  protected function ensureFieldTable($index_prefix, &$field, $type, $langcode, $base_table, $entity_id_field, $field_id_field) {
+  protected function ensureFieldTable($index_prefix, &$field, $type, $langcode, $base_table, $entity_id_field, $field_id_field, $delta) {
     $field_name = $field->getName();
     if (!isset($this->fieldTables[$index_prefix . $field_name])) {
       $entity_type_id = $this->sqlQuery->getMetaData('entity_type');
@@ -265,12 +308,12 @@ protected function ensureFieldTable($index_prefix, &$field, $type, $langcode, $b
       if ($field->getCardinality() != 1) {
         $this->sqlQuery->addMetaData('simple_query', FALSE);
       }
-      $this->fieldTables[$index_prefix . $field_name] = $this->addJoin($type, $table, "%alias.$field_id_field = $base_table.$entity_id_field", $langcode);
+      $this->fieldTables[$index_prefix . $field_name] = $this->addJoin($type, $table, "%alias.$field_id_field = $base_table.$entity_id_field", $langcode, $delta);
     }
     return $this->fieldTables[$index_prefix . $field_name];
   }
 
-  protected function addJoin($type, $table, $join_condition, $langcode) {
+  protected function addJoin($type, $table, $join_condition, $langcode, $delta = NULL) {
     $arguments = array();
     if ($langcode) {
       $entity_type_id = $this->sqlQuery->getMetaData('entity_type');
@@ -282,6 +325,11 @@ protected function addJoin($type, $table, $join_condition, $langcode) {
       $join_condition .= ' AND %alias.' . $langcode_key . ' = ' . $placeholder;
       $arguments[$placeholder] = $langcode;
     }
+    if (isset($delta)) {
+      $placeholder = ':delta' . $this->sqlQuery->nextPlaceholder();
+      $join_condition .= ' AND %alias.delta = ' . $placeholder;
+      $arguments[$placeholder] = $delta;
+    }
     return $this->sqlQuery->addJoin($type, $table, NULL, $join_condition, $arguments);
   }
 
diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/TablesInterface.php b/core/lib/Drupal/Core/Entity/Query/Sql/TablesInterface.php
index 214e130..2ccdfa5 100644
--- a/core/lib/Drupal/Core/Entity/Query/Sql/TablesInterface.php
+++ b/core/lib/Drupal/Core/Entity/Query/Sql/TablesInterface.php
@@ -11,8 +11,10 @@
    * Adds a field to a database query.
    *
    * @param string $field
-   *   If it contains a dot, then field name dot field column. If it doesn't
-   *   then entity property name.
+   *   If it doesn't contain a dot, then an entity base field name.
+   *   If it contains a dot, then either field name dot field column or
+   *   field name dot delta dot field column. Delta can be a numeric value or a
+   *   ? for any value.
    * @param string $type
    *   Join type, can either be INNER or LEFT.
    * @param string $langcode
diff --git a/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
index 8ee00bd..607c2c2 100644
--- a/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
+++ b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
@@ -3,6 +3,7 @@
 namespace Drupal\Core\Entity\Sql;
 
 use Drupal\Core\Entity\ContentEntityTypeInterface;
+use Drupal\Core\Entity\Query\QueryInterface;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 
 /**
@@ -203,7 +204,12 @@ public function getFieldColumnName(FieldStorageDefinitionInterface $storage_defi
       $column_name = count($storage_definition->getColumns()) == 1 ? $field_name :  $field_name . '__' . $property_name;
     }
     elseif ($this->requiresDedicatedTableStorage($storage_definition)) {
-      $column_name = !in_array($property_name, $this->getReservedColumns()) ? $field_name . '_' . $property_name : $property_name;
+      if ($property_name == QueryInterface::DELTA) {
+        $column_name = 'delta';
+      }
+      else {
+        $column_name = !in_array($property_name, $this->getReservedColumns()) ? $field_name . '_' . $property_name : $property_name;
+      }
     }
     else {
       throw new SqlContentEntityStorageException("Column information not available for the '$field_name' field.");
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php
index 0d4e5c4..2351113 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php
@@ -512,6 +512,44 @@ public function testNestedConditionGroups() {
     $this->assertResult(6, 14);
   }
 
+  /**
+   * Test queries with delta conditions.
+   */
+  public function testDelta() {
+    $figures = $this->figures;
+    // Test numeric delta value in field condition.
+    $this->queryResults = $this->factory->get('entity_test_mulrev')
+      ->condition("$figures.0.color", 'red')
+      ->sort('id')
+      ->execute();
+    // As unit 0 at delta 0 was the red triangle bit 0 needs to be set.
+    $this->assertResult(1, 3, 5, 7, 9, 11, 13, 15);
+
+    $this->queryResults = $this->factory->get('entity_test_mulrev')
+      ->condition("$figures.1.color", 'red')
+      ->sort('id')
+      ->execute();
+    // Delta 1 is not red.
+    $this->assertResult();
+
+    // Test '?' wildcard.
+    $this->queryResults = $this->factory->get('entity_test_mulrev')
+      ->condition("$figures.?.color", array('blue', 'red'), 'IN')
+      ->condition("$figures.?", array(0, 1), 'IN')
+      ->sort('id')
+      ->execute();
+    // Figure delta 0 or 1 can be blue or red, this matches a lot of entities.
+    $this->assertResult(1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15);
+
+    // Test '?' wildcard without other conditions.
+    $this->queryResults = $this->factory->get('entity_test_mulrev')
+      ->condition("$figures.?", 1)
+      ->sort('id')
+      ->execute();
+    // Entity needs to have atleast two figures.
+    $this->assertResult(3, 7, 11, 15);
+  }
+
   protected function assertResult() {
     $assert = array();
     $expected = func_get_args();
