简体   繁体   中英

COUNT/GROUP BY query isn't working

I want to display a list of duplicate values from some unioned tables. My goal is to display TWO columns, the first listing duplicate values from the field URL, the second displaying the number of instances of each value, like this...

africa (2)

usa (4)

I can't figure out what the problem with my query is. When I try it in MySQL > SQL, it gives me an "empty result set." I double-checked the tables, and they both have a field named URL.

UPDATE: I erred in grouping URL on each individual table; there are no duplicate values in a particular table. I tried to fix it by moving the GROUP BY clause to the end of the query.

But I'm still doing something wrong. When I paste the query into SQL, it should display several URL's with two instances each. Instead, it displays "earth 471." On my web page, I see the error Fatal error: [] operator not supported for strings

Also, at the end of the code, how do I display the second column?

$stm = $pdo->prepare("SELECT *
FROM (
 SELECT URL, COUNT(*) c FROM gw_geog_political
 UNION ALL 
 SELECT URL, COUNT(*) c FROM gw_geog
) AS Combined
GROUP BY URL HAVING c > 1");
 $stm->execute(array(
));

while ($row = $stm->fetch())
{
 $URL[] = $row['URL'];
}

echo join( $URL, '' );
  1. When I try it in MySQL > SQL, it gives me an "empty result set." I double-checked the tables, and they both have a field named URL.

    Had one (or both) not had a column named URL , you would have seen Error 1054 . An empty resultset indicates that the query ran without problem, but produced no results.

  2. I erred in grouping URL on each individual table; there are no duplicate values in a particular table. I tried to fix it by moving the GROUP BY clause to the end of the query.

    But I'm still doing something wrong. When I paste the query into SQL, it should display several URL's with two instances each. Instead, it displays "earth 471."

    By moving GROUP BY to the outer query, you're left with inner queries that use the COUNT() aggregate function but have no GROUP BY clause of their own. However, as documented under GROUP BY (Aggregate) Functions :

    If you use a group function in a statement containing no GROUP BY clause, it is equivalent to grouping on all rows.

    Therefore each constituent of the UNION will produce exactly one record (comprising an indeterminate URL and a count of the total number of records, of any URL , in the underlying table).

    That the grouping operation in the outer query results in resultset with only one record implies either that the indeterminate value of URL selected in each case happened to be the same (in which case the value of c is indeterminately selected from the two underlying results from the inner query), or else that one of the two tables is empty.

    To perform the aggregation in the outer query as you are attempting, you would need to move the COUNT() functions there too:

     SELECT URL, COUNT(*) c FROM ( SELECT URL FROM gw_geog_political UNION ALL SELECT URL FROM gw_geog ) AS Combined GROUP BY URL HAVING c > 1 

    However, since "there are no duplicate values in a particular table", what you're really trying to obtain is a list of URLs that appear in both tables (for which the COUNT() will always be two). This can more directly be effected by means of an inner join:

     SELECT URL FROM gw_geog_political JOIN gw_geog USING (URL) 

    If "duplicate values in a particular table" might exist in the future, you could simply add DISTINCT to the above query in order to remove them from the resultset—although to obtain the actual count would require a little more work:

     SELECT URL, COUNT(DISTINCT gp.id) + COUNT(DISTINCT g.id) AS c FROM gw_geog_political gp JOIN gw_geog g USING (URL) GROUP BY URL 

    However, in this case, your original approach (grouping within the inner queries) would probably be more efficient—you just need to group again in the outer query, summing the inner counts:

     SELECT URL, SUM(c) c FROM ( SELECT URL, COUNT(*) c FROM gw_geog_political GROUP BY URL UNION ALL SELECT URL, COUNT(*) c FROM gw_geog GROUP BY URL ) AS Combined GROUP BY URL HAVING c > 1 
  3. On my web page, I see the error Fatal error: [] operator not supported for strings

    This is probably arising because a non-empty string is assigned to your $URL variable some time before the code snippet you have shown. Consequently, the attempt to construct in it an array of result values using $URL[] = ... within the loop fails with the error that you see. You should initialise your desired variable to an empty array prior to entering the loop, just to be sure:

     $URL = array(); while ($row = $stm->fetch()) { $URL[] = $row['URL']; } 

    Note that the same result can be achieved by using PDO's fetchAll() method:

     $URL = $stm->fetchAll(PDO::FETCH_COLUMN, 0); 

    However it's generally a bad idea to load an entire resultset into a PHP array, since that can needlessly consume a lot of memory (and anyway you'll just have to loop a second time, over the resulting array, in order to operate upon it). If you're able to perform your ultimate operation (output in this case) whilst fetching the results, then that will often be much more efficient:

     while ($row = $stm->fetch()) { echo $row['URL'], PHP_EOL; } 
  4. Also, at the end of the code, how do I display the second column?

    As mentioned above, the count in each case will necessarily be two . But if you want to use other columns from the resultset, you can modify the loop accordingly:

     while ($row = $stm->fetch()) { echo "$row[URL] ($row[c])", PHP_EOL; } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM