Wednesday 13 January 2010

MYSQL and PHP, how do I show a random group of records where count >1


I've just added to my favourite #fridayflash list , a featured Author selection. Where I have been adding stories each week, there are naturally several authors appearing more than once. What I wanted to do, was feature one of these author on the page, by random selection, and list their stories.

I apologies if the language might seem a bit funny in this post, but from trying to do it, it was not what I quite expected and took a bit of googling. I am typing this post this way, in the hope someone with the same problem finds it easy on google.

Firstly my data is stored in the following table structure.


CREATE TABLE IF NOT EXISTS `fridayflash` (
  `sID` int(11) NOT NULL auto_increment,
  `week` int(11) NOT NULL,
  `sortA` varchar(1) NOT NULL,
  `title` varchar(200) NOT NULL,
  `author` varchar(200) NOT NULL,
  `twitter` varchar(200) NOT NULL,
  `link` varchar(200) NOT NULL,
  `review` varchar(200) NOT NULL,
  `notes` varchar(200) NOT NULL,
  PRIMARY KEY  (`sID`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=45 ;

The first thing I needed to was find out all of those authors who had more than one entry in the database. My SQL looked liked the following *

SELECT author
FROM fridayflash
GROUP BY author
HAVING COUNT( sID ) >1



The next thing, was to limit by select one of these records by random. To achieve this, I added the following two lines to the bottom of the query. 


SELECT author
FROM fridayflash
GROUP BY author
HAVING COUNT( sID ) >1
ORDER BY RAND( )
LIMIT 1



I now then wanted to select all the stories by my random selection and this is where I began to run into problems.  Firstly approaching this as if i was using Oracle of SQL Server and using nested queries, HAVING or WHERE. I ran into the error

'This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'


I found my solution here on this article on sub queries  and got the required result, by using the following SQL

SELECT *
FROM fridayflash
INNER JOIN (

SELECT author AS b
FROM fridayflash
GROUP BY author
HAVING COUNT( sID ) >1
ORDER BY RAND( )
LIMIT 1
) AS c ON fridayflash.author = c.b



I then created the following PHP Function **
function FeaturedAuthor()
{
$counter = 1;

$sql = "SELECT * FROM fridayflash
INNER JOIN (
SELECT author AS b
FROM fridayflash
GROUP BY author
HAVING COUNT( sID ) >1
ORDER BY RAND( )
LIMIT 1) AS c
ON fridayflash.author = c.b";

$result = mysql_query($sql)
or die(mysql_error());

if (mysql_num_rows($result) == 0)
{
echo "<em>No created.</em>";
} else {


while ($row = mysql_fetch_array($result))
{
If ($counter == 1)
{
echo "<h1>" ."<a href=http://twitter.com/" . $row['twitter'] .">". $row['author'] . " <a>" ."</h1>";
}

echo "<p><a href=" . $row['link'] . ">" . $row['title'] ."</a> " .
$row['review'] . "</i></p>";

$counter = $counter ++;
}
}


}




And you can see the result on the #fridayflash list page of my site, just under the Most Recent stories added. If you hit F5 you will see the featured author change.

*Yes, I know using author name is not an ideal key :-p, let me tell you sometime of a horror story involving a developer being allowed free roam on the company servers without any DBA's to distract you.
** I'm very slowly learning php, I am not happy with the use of the counter in the above to make sure the author name is only outputted once.  Suggestions ? 








2 comments:

  1. I have no idea what the above says, but it's a neat trick! :)

    ReplyDelete
  2. Cherish that not knowing, for the moment you do, its a slippery slope to damnation

    ReplyDelete

LinkWithin

Related Posts with Thumbnails