0

I am very new to SQL, and I am using MySQL, and I have a table that holds blogs. In that table, I have a column named "blog_category". I am trying to return DISTINCT values from the blog_category that appear at least (n) times. Example:

    blog_category
    -------------
    category_1
    category_1
    category_2
    category_3
    category_3
    category_4
    category_4
    category_1
    category_1
    category_2
    category_2

I only want to return the categories that appear say, at least 3 times (greater than or equal to 3).

I can get it to display the ones that appear more than just once with the DISTINCT keyword, but I only want the ones that actually appear more than the specified amount of times, in this case just the ones that appear at least than 3 times.

So in this case I only want to return "category_1" and "category_2".

I have tried numerous ways, but nothing seems to work, I keep getting the following error:

Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean
given in [FILE NAME OMITTED] on line 101 

Here are some of the things I've tried:

$query = "SELECT DISTINCT blog_category 
          FROM blog_posts 
          HAVING COUNT (blog_category) >= 3";

$query = "SELECT DISTINCT blog_category 
          FROM blog_posts 
          WHERE blog_category IN
          (SELECT blog_category
          HAVING (COUNT (blog_category) >= 3))";

$query = "SELECT DISTINCT blog_category 
          FROM blog_posts 
          WHERE blog_category 
          HAVING COUNT(blog_category) >= 3";

$query = "SELECT DISTINCT blog_category 
          FROM blog_posts 
          WHERE COUNT(blog_category) >= 3";

BELOW ARE SUGGESTED ANSWERS FROM OTHER USERS, THAT I HAVE TRIED AND HAD NO LUCK WITH.....

$query = "SELECT blog_category 
          FROM blog_posts 
          GROUP BY blog_category
          HAVING COUNT(*) >= 3";

HERE IS THE FULL SECTION OF CODE BEING RAN (I tested straight on the SQL test part of the server and it works just fine, but when I run the actual full code it keeps returning that the query is false) :

$query = "SELECT blog_category 
        FROM blog_posts
        GROUP BY blog_category
        HAVING COUNT(*) > 2)";

        $result = mysqli_query( $conn, $query );

        if( mysqli_num_rows( $result ) > 0 ) {
            while( $row = mysqli_fetch_assoc($result) ) {
                echo "<ul>";
                echo "<li>" . $row['blog_category'] . "</p>";
                echo "</ul>";           
            }
        }
Dustin Hammack
  • 154
  • 1
  • 1
  • 15
  • 3
    remove distinct add `group by blog_Category` after where; before having. if no where. – xQbert Oct 17 '17 at 20:10
  • See https://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-a-very-simple-sql-query – Strawberry Oct 17 '17 at 20:23
  • looks like error is related to the code you wrote after this query. Add the code with mysqli functions or add the code of whatever you are doing with $query. That seems to be the actual problem according to the error you wrote in your question. – Harshil Doshi Oct 17 '17 at 20:27
  • 1
    It's not about "luck", it's about having a *specification*, *sample data* and *expected output*. The query pattern provided by Gordon is the normative approach. If the query is returning an unexpected result, that could be investigated. If the query is throwing an error, that could also be investigated. But explaining the observed behavior as "nothing seems to work" and "had no luck with" is an inadequate description of the actual problem. https://ericlippert.com/2014/03/05/how-to-debug-small-programs/ – spencer7593 Oct 17 '17 at 20:28
  • @spencer7593 First off, it's not a small program by any means at this point, but this is the only part that is returning an error, and if you read the whole post, I put the error code that is being returned. So explain again what is not adequate here! – Dustin Hammack Oct 17 '17 at 20:31
  • @Harshil if I remove the GROUP BY and the HAVING COUNT, the code works just fine. It's only when I add those clauses, that the code fails. So without it, it returns all counts of categories as expected. If I add DISTINCT (without GROUP BY or HAVING COUNT) it works as expected returning each category only once. So how can it be in the code after the query? (legitimately asking here, not being a smartass) – Dustin Hammack Oct 17 '17 at 20:38
  • Because from the given sample data, there is no way Gordon's query can fail. Hence, my guess is there is something wrong the way you are using/handling $query somewhere down in the code. – Harshil Doshi Oct 17 '17 at 20:43
  • @Harshil Just posted the actual full code that is being run against the query.... – Dustin Hammack Oct 17 '17 at 20:45
  • Try this & comment here what does it prints: if ($result = mysqli_query($conn, $query)) { printf("Select returned %d rows.\n", mysqli_num_rows($result));} – Harshil Doshi Oct 17 '17 at 20:50
  • 1
    *Check the return the query execution `mysqli_query`, and if it's FALSE, retrieve the MySQL error using `mysqli_error` function.* e.g. **`if(!$result) { printf(mysqli_error($conn)); }`** – spencer7593 Oct 17 '17 at 20:54
  • @Harshil it didn't print anything for me. – Dustin Hammack Oct 17 '17 at 20:58
  • try @spencer7593 's code given in latest comment – Harshil Doshi Oct 17 '17 at 21:00
  • Thank you for your NEW answer @spencer7593, however, the returned error does not make sense (to me), the returned error is ----- "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 4 " ------ I say it doesn't make sense because all that's on line 4 is session_start() and again it's working just fine if I remove EVERYTHING after the FROM blog_category, (but of course it returns all categories) – Dustin Hammack Oct 17 '17 at 21:07
  • Actually, I haven't, so can't comment on that. – Strawberry Oct 17 '17 at 21:10
  • 1
    It's reporting line 4 of the SQL query text, not the PHP program. MySQL is saying there's a *syntax* error in the SQL that was sent to it. There's a spurious (unmatched) closing paren,character at the end ... the paren after the literal ... `> 2)"`; Not at all clear why that closing paren was added. (It's not in the query provided in Gordon Linoff's answer.) – spencer7593 Oct 17 '17 at 21:10
  • Ok ok ok, I feel like an idiot, I had a parenthesis at the end of the HAVING COUNT line.... It's working completely as expected now. Thank you all for the help!! – Dustin Hammack Oct 17 '17 at 21:15
  • @spencer7593 yeah I just found it before I seen your response about it. Thank you for the help. It's completely working as it should be now! – Dustin Hammack Oct 17 '17 at 21:17

3 Answers3

5

You need GROUP BY:

SELECT blog_category 
FROM blog_posts 
GROUP BY blog_category
HAVING COUNT(*) >= 3;

Basically, you should never be using SELECT DISTINCT with aggregation functions (such as COUNT(*)). Whenever you have functions such as COUNT(), MIN(), MAX(), and so on, you should either have a GROUP BY or be expecting exactly one row in the result set.

Admittedly, there are exceptions. In some databases, you might do this with analytic functions that don't have aggregation equivalents. That does not apply to MySQL.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
  • 1
    What output/error you got for the above query? – Harshil Doshi Oct 17 '17 at 20:25
  • It keeps telling me the query returned false with error: Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given in [FILE NAME OMITTED] on line 101 – Dustin Hammack Oct 17 '17 at 20:26
  • Ok, so I have ran it again on the actual server, and it's working just fine and as expected (with your query answer). But for some reason in the code it's not working. But the code returns just fine if I remove the Group By and the Having Count. So basically just the SELECT and FROM statements work just fine in the code. I'm not understanding what is wrong. – Dustin Hammack Oct 17 '17 at 20:34
1

You have right idea with a having clause, but you're missing a group by clause to apply the count per group (i.e., per distinct value of blog_category):

SELECT   blog_category 
FROM     blog_posts 
GROUP BY blog_category
HAVING   COUNT(*) >= 3
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • @DustinHammack can you elaborate what exactly didn't work here? – Mureinik Oct 17 '17 at 20:20
  • I tried the exact code you shared, and I get the same error as every other time, telling me the query returned false.... The following error is the error I continue to receive: Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given in [FILE NAME OMITTED] on line 101 – Dustin Hammack Oct 17 '17 at 20:22
0

Like this:

SELECT blog_category 
FROM blog_posts
GROUP BY blog_category
HAVING COUNT (blog_category) >= 3

You've got to GROUP BY so it knows how to count.

Vexen Crabtree
  • 339
  • 3
  • 16
  • Before answering, I duplicated your DB in MS Access and ran the query on it, and it successfully showed me just cat1 and cat2. Are there other features in your DB schema that might be relevant? What did it return? – Vexen Crabtree Oct 17 '17 at 20:21
  • Just the same error every time, telling me that the query returned false... Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given in [FILE NAME OMITTED] on line 101 – Dustin Hammack Oct 17 '17 at 20:25
  • 1
    I suggest that you post your code together with the query provided by the answers. – isaace Oct 17 '17 at 20:33