diff --git a/flag.inc b/flag.inc
index 25228e0..7da1af7 100644
--- a/flag.inc
+++ b/flag.inc
@@ -721,7 +721,7 @@ class flag_flag {
         'timestamp' => REQUEST_TIME,
       ))
       ->execute();
-    $this->_update_count($content_id);
+    $this->_increase_count($content_id);
     return $fcid;
   }
 
@@ -748,34 +748,58 @@ class flag_flag {
       ->fetchField();
     if ($fcid) {
       db_delete('flag_content')->condition('fcid', $fcid)->execute();
-      $this->_update_count($content_id);
+      $this->_decrease_count($content_id);
     }
     return $fcid;
   }
 
   /**
-   * Updates the flag count for this content
+   * Increases the flag count for a piece of content.
+   *
+   * @param $content_id
+   *   For which item should the count be increased.
+   * @param $number
+   *   The amount of counts to increasing. Defaults to 1.
    *
    * @private
-   */
-  function _update_count($content_id) {
-    $count = db_select('flag_content', 'fc')->fields('fc', array('fcid'))
+  */
+  function _increase_count($content_id, $number = 1) {
+    db_merge('flag_counts')
+      ->key(array(
+        'fid' => $this->fid,
+        'content_id' => $content_id,
+      ))
+      ->fields(array(
+        'content_type' => $this->content_type,
+        'count' => $number,
+      ))
+      ->expression('count', 'count + :inc', array(':inc' => $number))
+      ->execute();
+  }
+
+  /**
+   * Decreases the flag count for a piece of content.
+   *
+   * @param $content_id
+   *   For which item should the count be descreased.
+   * @param $number
+   *   The amount of counts to decrease. Defaults to 1.
+   *
+   * @private
+  */
+  function _decrease_count($content_id, $number = 1) {
+    db_update('flag_counts')
+      ->expression('count', 'count - :inc', array(':inc' => $number))
       ->condition('fid', $this->fid)
       ->condition('content_id', $content_id)
-      ->countQuery()->execute()->fetchField();
-    if ($count == 0) {
-      db_delete('flag_counts')->condition('fid', $this->fid)->condition('content_id', $content_id)->execute();
-    }
-    else {
-      db_merge('flag_counts')
-        ->key(array('fid' => $this->fid, 'content_id' => $content_id))
-        ->fields(array(
-          'content_type' => $this->content_type,
-          'count' => $count,
-          'last_updated' => REQUEST_TIME,
-        ))
-        ->execute();
-    }
+      ->execute();
+
+    // Delete rows with count 0, for data consistency and space-saving.
+    db_delete('flag_counts')
+      ->condition('fid', $this->fid)
+      ->condition('content_id', $content_id)
+      ->condition('count', 0)
+      ->execute();
   }
 
   /**
diff --git a/flag.module b/flag.module
index a7bef47..11f8d1d 100644
--- a/flag.module
+++ b/flag.module
@@ -557,15 +557,16 @@ function flag_user_login(&$edit, &$account) {
   // Migrate anonymous flags to this user's account.
   if (module_exists('session_api') && ($sid = flag_get_sid(0))) {
     // Get a list of flag_content IDs that will be moved over.
-    $fcids = db_select('flag_content', 'fc')
-      ->fields('fc', array('fcid'))
+    $duplicate_flaggings = array();
+    $flaggings = db_select('flag_content', 'fc')
+      ->fields('fc', array('fcid', 'fid', 'content_id'))
       ->condition('uid', 0)
       ->condition('sid', $sid)
       ->execute()
-      ->fetchCol('fcid');
+      ->fetchAllAssoc('fcid', PDO::FETCH_ASSOC);
 
     // Convert anonymous flaggings to their authenticated account.
-    foreach ($fcids as $fcid) {
+    foreach ($flaggings as $fcid => $flagging) {
       // Each update is wrapped in a try block to prevent unique key errors.
       // Any duplicate content that was flagged as anonoymous is deleted in the
       // subsequent db_delete() call.
@@ -579,15 +580,18 @@ function flag_user_login(&$edit, &$account) {
           ->execute();
       }
       catch (Exception $e) {
-        NULL;
+        $duplicate_flaggings[$fcid] = $flagging;
       }
     }
 
-    // Delete any remaining flags this user had as an anonymous user.
-    db_delete('flag_content')
-      ->condition('uid', 0)
-      ->condition('sid', $sid)
-      ->execute();
+    // Delete any remaining flags this user had as an anonymous user. We use the
+    // proper unflag action here to make sure the count gets decremented again
+    // and so that other modules can clean up their tables if needed.
+    $anonymous_user = drupal_anonymous_user();
+    foreach ($duplicate_flaggings as $fcid => $flagging) {
+      $flag = flag_get_flag(NULL, $flagging['fid']);
+      $flag->flag('unflag', $flagging['content_id'], $anonymous_user, TRUE);
+    }
 
     // Clean up anonymous cookies.
     FlagCookieStorage::drop();
