diff --git a/core/modules/views/src/EntityViewsData.php b/core/modules/views/src/EntityViewsData.php
index cc7b7be..81f0487 100644
--- a/core/modules/views/src/EntityViewsData.php
+++ b/core/modules/views/src/EntityViewsData.php
@@ -112,8 +112,10 @@ public function getViewsData() {
     $data = [];
 
     $base_table = $this->entityType->getBaseTable() ?: $this->entityType->id();
+    $views_revision_base_table = NULL;
     $revisionable = $this->entityType->isRevisionable();
     $base_field = $this->entityType->getKey('id');
+    $revision_field = $this->entityType->getKey('revision');
 
     $revision_table = '';
     if ($revisionable) {
@@ -240,6 +242,16 @@ public function getViewsData() {
       // table.
       $entity_keys = $this->entityType->getKeys();
       $duplicate_fields = array_intersect_key($entity_keys, array_flip(['id', 'revision', 'bundle']));
+      // Make note of some information so that table joins can be applied for
+      // base fields that have dedicated tables.
+      $main_tables = array_filter([$base_table, $data_table, $revision_table, $revision_data_table]);
+      $dedicated_data_tables = [];
+      foreach ($field_definitions as $field_name => $field_definition) {
+        $storage_definition = $field_definition->getFieldStorageDefinition();
+        if ($revisionable && $storage_definition->isMultiple()) {
+          $dedicated_data_tables[] = $table_mapping->getFieldTableName($field_name);
+        }
+      }
       // Iterate over each table we have so far and collect field data for each.
       // Based on whether the field is in the field_definitions provided by the
       // entity manager.
@@ -247,6 +259,20 @@ public function getViewsData() {
       //   storage.
       // @todo https://www.drupal.org/node/2337511
       foreach ($table_mapping->getTableNames() as $table) {
+        // Provide joins for base fields with dedicated storage.
+        if (!in_array($table, $main_tables)) {
+          $is_revision = !in_array($table, $dedicated_data_tables);
+          $data[$table]['table']['group'] = !$is_revision ? $this->entityType->getLabel() : $this->t('@entity_type revision', ['@entity_type' => $this->entityType->getLabel()]);
+          $data[$table]['table']['provider'] = $this->entityType->getProvider();
+          $data[$table]['table']['join'][$is_revision ? $views_revision_base_table : $views_base_table] = [
+            'left_field' => $is_revision ? $revision_field : $base_field,
+            'field' => 'entity_id',
+            'extra' => array(
+              array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE),
+            ),
+          ];
+        }
+
         foreach ($table_mapping->getFieldNames($table) as $field_name) {
           // To avoid confusing duplication in the user interface, for fields
           // that are on both base and data tables, only add them on the data
diff --git a/core/modules/views/tests/src/Unit/EntityViewsDataTest.php b/core/modules/views/tests/src/Unit/EntityViewsDataTest.php
index e6d8f9f..446f0cd 100644
--- a/core/modules/views/tests/src/Unit/EntityViewsDataTest.php
+++ b/core/modules/views/tests/src/Unit/EntityViewsDataTest.php
@@ -161,6 +161,12 @@ protected function setupBaseFields(array $base_fields) {
       ->setTranslatable(TRUE)
       ->setSetting('max_length', 255);
 
+    // A base field with cardinality > 1
+    $base_fields['string']  = BaseFieldDefinition::create('string')
+      ->setLabel('Strong')
+      ->setTranslatable(TRUE)
+      ->setCardinality(2);
+
     foreach ($base_fields as $name => $base_field) {
       $base_field->setName($name);
     }
@@ -377,6 +383,10 @@ protected function setupFieldStorageDefinition() {
     $homepage_field_storage_definition->expects($this->any())
       ->method('getSchema')
       ->willReturn(UriItem::schema($homepage_field_storage_definition));
+    $string_field_storage_definition = $this->getMock('Drupal\Core\Field\FieldStorageDefinitionInterface');
+    $string_field_storage_definition->expects($this->any())
+      ->method('getSchema')
+      ->willReturn(StringItem::schema($string_field_storage_definition));
 
     // Setup the user_id entity reference field.
     $this->entityManager->expects($this->any())
@@ -412,6 +422,7 @@ protected function setupFieldStorageDefinition() {
         'name' => $name_field_storage_definition,
         'description' => $description_field_storage_definition,
         'homepage' => $homepage_field_storage_definition,
+        'string' => $string_field_storage_definition,
         'user_id' => $user_id_field_storage_definition,
         'revision_id' => $revision_id_field_storage_definition,
       ]);
@@ -439,7 +450,7 @@ public function testBaseTableFields() {
     $table_mapping = $this->getMock('Drupal\Core\Entity\Sql\TableMappingInterface');
     $table_mapping->expects($this->any())
       ->method('getTableNames')
-      ->willReturn(['entity_test']);
+      ->willReturn(['entity_test', 'entity_test__string']);
     $table_mapping->expects($this->any())
       ->method('getColumnNames')
       ->willReturnMap([
@@ -451,11 +462,13 @@ public function testBaseTableFields() {
         ['description', ['value' => 'description__value', 'format' => 'description__format']],
         ['homepage', ['value' => 'homepage']],
         ['user_id', ['target_id' => 'user_id']],
+        ['string', ['value' => 'value']],
       ]);
     $table_mapping->expects($this->any())
       ->method('getFieldNames')
       ->willReturnMap([
-        ['entity_test', ['id', 'uuid', 'type', 'langcode', 'name', 'description', 'homepage', 'user_id']]
+        ['entity_test', ['id', 'uuid', 'type', 'langcode', 'name', 'description', 'homepage', 'user_id']],
+        ['entity_test__string', ['string']],
       ]);
 
     $this->entityStorage->expects($this->once())
@@ -493,6 +506,18 @@ public function testBaseTableFields() {
     $relationship = $data['entity_test']['user_id']['relationship'];
     $this->assertEquals('users_field_data', $relationship['base']);
     $this->assertEquals('uid', $relationship['base field']);
+
+    $this->assertStringField($data['entity_test__string']['string']);
+    $this->assertField($data['entity_test__string']['string'], 'string');
+    $this->assertEquals([
+      'left_field' => 'id',
+      'field' => 'entity_id',
+      'extra' => [[
+        'field' => 'deleted',
+        'value' => 0,
+        'numeric' => TRUE,
+      ]],
+    ], $data['entity_test__string']['table']['join']['entity_test']);
   }
 
   /**
@@ -533,7 +558,7 @@ public function testDataTableFields() {
     $table_mapping = $this->getMock('Drupal\Core\Entity\Sql\TableMappingInterface');
     $table_mapping->expects($this->any())
       ->method('getTableNames')
-      ->willReturn(['entity_test_mul', 'entity_test_mul_property_data']);
+      ->willReturn(['entity_test_mul', 'entity_test_mul_property_data', 'entity_test_mul__string']);
     $table_mapping->expects($this->any())
       ->method('getColumnNames')
       ->willReturnMap([
@@ -545,12 +570,14 @@ public function testDataTableFields() {
         ['description', ['value' => 'description__value', 'format' => 'description__format']],
         ['homepage', ['value' => 'homepage']],
         ['user_id', ['target_id' => 'user_id']],
+        ['string', ['value' => 'value']],
       ]);
     $table_mapping->expects($this->any())
       ->method('getFieldNames')
       ->willReturnMap([
         ['entity_test_mul', ['uuid']],
         ['entity_test_mul_property_data', ['id', 'type', 'langcode', 'name', 'description', 'homepage', 'user_id']],
+        ['entity_test_mul__string', ['string']],
       ]);
 
     $table_mapping->expects($this->any())
@@ -620,6 +647,18 @@ public function testDataTableFields() {
     $relationship = $data['entity_test_mul_property_data']['user_id']['relationship'];
     $this->assertEquals('users_field_data', $relationship['base']);
     $this->assertEquals('uid', $relationship['base field']);
+
+    $this->assertStringField($data['entity_test_mul__string']['string']);
+    $this->assertField($data['entity_test_mul__string']['string'], 'string');
+    $this->assertEquals([
+      'left_field' => 'id',
+      'field' => 'entity_id',
+      'extra' => [[
+        'field' => 'deleted',
+        'value' => 0,
+        'numeric' => TRUE,
+      ]],
+    ], $data['entity_test_mul__string']['table']['join']['entity_test_mul']);
   }
 
   /**
@@ -654,7 +693,7 @@ public function testRevisionTableFields() {
     $table_mapping = $this->getMock('Drupal\Core\Entity\Sql\TableMappingInterface');
     $table_mapping->expects($this->any())
       ->method('getTableNames')
-      ->willReturn(['entity_test_mulrev', 'entity_test_mulrev_revision', 'entity_test_mulrev_property_data', 'entity_test_mulrev_property_revision']);
+      ->willReturn(['entity_test_mulrev', 'entity_test_mulrev_revision', 'entity_test_mulrev_property_data', 'entity_test_mulrev_property_revision', 'entity_test_mulrev__string', 'entity_test_mulrev_revision__string']);
     $table_mapping->expects($this->any())
       ->method('getColumnNames')
       ->willReturnMap([
@@ -667,6 +706,7 @@ public function testRevisionTableFields() {
         ['homepage', ['value' => 'homepage']],
         ['user_id', ['target_id' => 'user_id']],
         ['revision_id', ['value' => 'id']],
+        ['string', ['value' => 'value']],
       ]);
     $table_mapping->expects($this->any())
       ->method('getFieldNames')
@@ -675,6 +715,8 @@ public function testRevisionTableFields() {
         ['entity_test_mulrev_revision', ['id', 'revision_id', 'langcode']],
         ['entity_test_mulrev_property_data', ['id', 'revision_id', 'langcode', 'name', 'description', 'homepage', 'user_id']],
         ['entity_test_mulrev_property_revision', ['id', 'revision_id', 'langcode', 'name', 'description', 'homepage', 'user_id']],
+        ['entity_test_mulrev__string', ['string']],
+        ['entity_test_mulrev_revision__string', ['string']],
       ]);
 
     $table_mapping->expects($this->any())
@@ -768,6 +810,30 @@ public function testRevisionTableFields() {
     $relationship = $data['entity_test_mulrev_property_revision']['user_id']['relationship'];
     $this->assertEquals('users_field_data', $relationship['base']);
     $this->assertEquals('uid', $relationship['base field']);
+
+    $this->assertStringField($data['entity_test_mulrev__string']['string']);
+    $this->assertField($data['entity_test_mulrev__string']['string'], 'string');
+    $this->assertEquals([
+      'left_field' => 'id',
+      'field' => 'entity_id',
+      'extra' => [[
+        'field' => 'deleted',
+        'value' => 0,
+        'numeric' => TRUE,
+      ]],
+    ], $data['entity_test_mulrev__string']['table']['join']['entity_test_mulrev_property_data']);
+
+    $this->assertStringField($data['entity_test_mulrev_revision__string']['string']);
+    $this->assertField($data['entity_test_mulrev_revision__string']['string'], 'string');
+    $this->assertEquals([
+      'left_field' => 'id',
+      'field' => 'entity_id',
+      'extra' => [[
+        'field' => 'deleted',
+        'value' => 0,
+        'numeric' => TRUE,
+      ]],
+    ], $data['entity_test_mulrev_revision__string']['table']['join']['entity_test_mulrev_property_revision']);
   }
 
   /**
