Extra checkbox in tableselect rows
That happens because you are using a #tableselect form element, which is clearly described as follows:


  A table created with a far left column of radios or checkboxes. Build the table headings and columns with the #headers property, and the rows with the #options property. See Adding checkboxes to a table for a full explanation.


What you are looking for is a table, which is a theme function. See for example the following code, used by Drupal core.

function aggregator_view() {
  $result = db_query('SELECT f.fid, f.title, f.url, f.refresh, f.checked, f.link, f.description, f.hash, f.etag, f.modified, f.image, f.block, COUNT(i.iid) AS items FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.url, f.refresh, f.checked, f.link, f.description, f.hash, f.etag, f.modified, f.image, f.block ORDER BY f.title');

  $output = '&lt;h3&gt;' . t('Feed overview') . '&lt;/h3&gt;';

  $header = array(
    t('Title'),
    t('Items'),
    t('Last update'),
    t('Next update'),
    array(
      'data' =&gt; t('Operations'),
      'colspan' =&gt; '3',
    ),
  );
  $rows = array();
  foreach ($result as $feed) {
    $rows[] = array(
      l($feed-&gt;title, "aggregator/sources/$feed-&gt;fid"),
      format_plural($feed-&gt;items, '1 item', '@count items'),
      ($feed-&gt;checked ? t('@time ago', array('@time' =&gt; format_interval(REQUEST_TIME - $feed-&gt;checked))) : t('never')),
      ($feed-&gt;checked &amp;&amp; $feed-&gt;refresh ? t('%time left', array('%time' =&gt; format_interval($feed-&gt;checked + $feed-&gt;refresh - REQUEST_TIME))) : t('never')),
      l(t('edit'), "admin/config/services/aggregator/edit/feed/$feed-&gt;fid"),
      l(t('remove items'), "admin/config/services/aggregator/remove/$feed-&gt;fid"),
      l(t('update items'), "admin/config/services/aggregator/update/$feed-&gt;fid", array('query' =&gt; array('token' =&gt; drupal_get_token("aggregator/update/$feed-&gt;fid")))),
    );
  }
  $output .= theme('table', array('header' =&gt; $header, 'rows' =&gt; $rows, 'empty' =&gt; t('No feeds available. &lt;a href="@link"&gt;Add feed&lt;/a&gt;.', array('@link' =&gt; url('admin/config/services/aggregator/add/feed')))));

  $result = db_query('SELECT c.cid, c.title, COUNT(ci.iid) as items FROM {aggregator_category} c LEFT JOIN {aggregator_category_item} ci ON c.cid = ci.cid GROUP BY c.cid, c.title ORDER BY title');

  $output .= '&lt;h3&gt;' . t('Category overview') . '&lt;/h3&gt;';

  $header = array(t('Title'), t('Items'), t('Operations'));
  $rows = array();
  foreach ($result as $category) {
    $rows[] = array(l($category-&gt;title, "aggregator/categories/$category-&gt;cid"), format_plural($category-&gt;items, '1 item', '@count items'), l(t('edit'), "admin/config/services/aggregator/edit/category/$category-&gt;cid"));
  }
  $output .= theme('table', array('header' =&gt; $header, 'rows' =&gt; $rows, 'empty' =&gt; t('No categories available. &lt;a href="@link"&gt;Add category&lt;/a&gt;.', array('@link' =&gt; url('admin/config/services/aggregator/add/category')))));

  return $output;
}


In your case, your code should simply be similar to the following one. (See also the comments in the code.)

function popups_list_form($form, &amp;$form_state) {
  // This variable is never used; remove it.
  // global $base_url;

  $header = array("Title", "Popup");
  $result = db_query("SELECT * FROM popups");

  // The following bracket is wrong placed. Remove it from your code.
  // }

  $rows = array();

  foreach ($result as $row) {                   
    $rows[] = array($row-&gt;title, $row-&gt;popup_org_name);
  }

  $form['table'] = array(
    '#theme' =&gt; 'table',
    '#header' =&gt; $header,
    '#rows' =&gt; $rows,
    '#empty' =&gt; t('No Popups Available'),
  );

  return $form;   
}