Jump to content

search 2 fields in a database and sort results


flash gordon

Recommended Posts

I was trying to pay someone to do this, but things are not looking hopeful now....

 

Anyway, I need to search 2 fields in a database table that have text in them. So I need to search for "foo, bar, cat" in to fields. Then I need to return the greatest number of matches first, and so on down the line.

 

I do not have system level access to the server so Full-Text search methods are out.

Can anyone give some pointers how to do this?

 

:)

Link to comment
Share on other sites

try

<?php
include 'db2.php'; // db connect stuff
/**
* create a temp table to effectively normalize your table  
*/
$sql = "CREATE TEMPORARY TABLE tableB SELECT id, a FROM tableA";
mysql_query($sql) or die (mysql_error()."<p>$sql</p>");

$sql = "INSERT INTO tableB SELECT id, b FROM tableA";
mysql_query($sql) or die (mysql_error()."<p>$sql</p>");

/**
* now it's a simple count query'
*/
$sql = "select a, COUNT(*) as n FROM tableB
        WHERE a IN ('foo', 'bar', 'cat')
        GROUP BY a
        ORDER BY n DESC";
$res = mysql_query($sql) or die (mysql_error()."<p>$sql</p>");

while (list($a,$n) = mysql_fetch_row($res)) {
    echo "$a : $n <br>";
}
?>

 

My data

id, a, b
----------------
1, 'foo', 'x'
2, 'foo', 'bar'
3, 'y', 'cat'
4, 'bar', 'z'
5, 'cat', 'foo'
6, 'x', 'foo'
7, 'cat', 'bar'
8, 'cat', 'foo'
9, 'x', 'y'
10, 'bar', 'foo'
11, 'foo', 'bar'
12, 'foo', 'foo'

 

My results

foo : 9 
bar : 5 
cat : 4 

Link to comment
Share on other sites

Thanks for the reply :)

 

I don't think I'm getting it.

<?php

$username = "";
$password = "";
$db       = "";
$table    = ""; 

// Conect to the database.
$cnx = mysql_connect('localhost', $username, $password) or die ("Could not connect");
mysql_select_db($db,  $cnx) or die (mysql_error());


$sql = "select keywords, composer, COUNT(*) as n FROM $table
        WHERE keywords IN ('foo', 'bar', 'cat')
        GROUP BY keywords
        ORDER BY n DESC";
$res = mysql_query($sql) or die (mysql_error()."<p>$sql</p>");

// and i did change the vars here to match what I need.
// i tried several different ways.
while (list($a,$n) = mysql_fetch_row($res)) {
    echo "$a : $n <br>";
}

?> 

tablesf4.jpg

 

Running that code gives me no errors, but no results (even before I stuck commas in the table). I need to search composer and keywords and sort those 2 fields.

 

Thanks guys

:)

Link to comment
Share on other sites

$search = $_GET['search'];
// $search = "foo, sad, two words, monkey"; 

// search database for the words above in the 'keywords' and 'composer' field

 

Output:

id 1 --> because it has three matches (foo, sad, and monkey)

id 4 --> because it has two matches (sad and "two words")

id 2 --> because it has one match (sad)

id 3 --> because it has one match (sad)

 

I'll eventually want to echo all fields except keywords, but I think I can take care of that part once I get the finding and sorting taken care of. Something like this is how I will format it once I get the search engine happening:

<?xml version="1.0" encoding="iso-8859-1"?>
<matches>

<cue id="1" url="music/heart.mp3" name="In The Heart">
	<composer>Michael Jackson</composer>
	<time>3000</time>
	<description>Do the Beat to the heart</description>
</cue>

<cue id="4" url="music/credits.mp3" name="Perfect Ending">
	<composer>Michael Thompson</composer>
	<time>1421</time>
	<description>Music over the credits</description>
</cue>

      ....continue on......

</matches>

 

Thanks for your help :)

Link to comment
Share on other sites

-- phpMyAdmin SQL Dump
-- version 2.9.1.1
-- http://www.phpmyadmin.net
-- 
-- Host: localhost
-- Generation Time: Apr 08, 2007 at 12:46 PM
-- Server version: 5.0.27
-- PHP Version: 5.2.0
-- 
-- Database: `digit`
-- 

-- --------------------------------------------------------

-- 
-- Table structure for table `cues`
-- 

CREATE TABLE `cues` (
  `id` int(11) NOT NULL auto_increment,
  `url` varchar(255) collate latin1_general_ci NOT NULL,
  `name` tinytext collate latin1_general_ci NOT NULL,
  `composer` tinytext collate latin1_general_ci NOT NULL,
  `time` int(11) NOT NULL,
  `description` text collate latin1_general_ci NOT NULL,
  `keywords` text collate latin1_general_ci NOT NULL,
  `demo` tinyint(1) NOT NULL,
  `saved` tinyint(1) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=5 ;

-- 
-- Dumping data for table `cues`
-- 

INSERT INTO `cues` VALUES (1, 'music/heart.mp3', 'In The Heart', 'Michael Jackson', 3000, 'Do the Beat to the heart', 'monkey, sad, foo, mustard, Ron', 0, 1);
INSERT INTO `cues` VALUES (2, 'music/mudd.mp3', 'Mudd ', 'Michael Jackson', 4352, 'In the Mudd', 'foodinkle, Ron, mud, mudd, sad ', 0, 1);
INSERT INTO `cues` VALUES (3, 'music/tense.mp3', 'Movie Music', 'Michael Jackson', 7452, 'Used a film ', 'movie, music, ron, sad, happy', 0, 1);
INSERT INTO `cues` VALUES (4, 'music/credits.mp3', 'Perfect Ending', 'Michael Thompson', 1421, 'Music over the credits', 'sad, short, minor, mud, complex, two words,', 0, 1);

 

Thanks mate :)

Link to comment
Share on other sites

As data more complex than envisaged in earlier solution, resorted to PHP rather than just SQL

 

<?php
include '../test/db2.php';

$search = array('foo', 'sad', 'two words', 'monkey');

$sql = "SELECT id, composer, keywords FROM cues";
$res = mysql_query($sql);
$data = array();
/**
* create an array of keywords from both fields
*/
while (list($i, $c, $k)= mysql_fetch_row($res)) {
    echo "$i, $c, $k<br>";
    $a = explode(' ', $c);
    $b = explode(',', $k);
    $tmp = array_merge($a, $b);
    /**
    * trim unwanted spaces from keywords
    */
    foreach($tmp as $k=>$v) {
        $tmp[$k] = trim($v);
    }
    $data[$i] =  $tmp;
}


/**
* find matching words
*/
foreach ($data as $k=>$a) {
    $data[$k] = array_intersect($a, $search);
}

/**
* sort the array based on jeyword content
*/
uasort ($data, 'mysort');

function mysort ($a, $b)
{
    $ka = count($a);
    $kb = count($b);
    
    if ($ka==$kb) return 0;
    return ($ka > $kb) ? -1 : 1;
}

/**
* view sorted array
*/
echo '<pre>Results ', print_r($data, true), '</pre>';
?>

Link to comment
Share on other sites

Thanks for the reply Barand.

 

Is there any way to do this, where I'm not selecting everything in the database and then looping through it? The database is going to have 10,000+ records in it. Is it possible to do it why mySQL like what you had above?

$sql = "select a, COUNT(*) as n FROM tableB
        WHERE a IN ('foo', 'bar', 'cat')
        GROUP BY a
        ORDER BY n DESC";

 

If not, at least I got something that words :)

Thanks again, mate.

Link to comment
Share on other sites

[code]
CREATE TEMPORARY TABLE tmp_cues
SELECT id  FROM cues WHERE keywords LIKE '%two words%'
UNION
SELECT id FROM cues WHERE keywords LIKE '%sad%'
UNION
SELECT id FROM cues WHERE keywords LIKE '%foo%'
UNION
SELECT id FROM cues WHERE keywords LIKE '%monkey%' ;

 

followed by

 


SELECT id, COUNT(*) as t FROM tmp_cues
GROUP BY id
ORDER BY t DESC

[/code]

Link to comment
Share on other sites

I'd redesign the table so you had a keyword table, each row with a single keyword + id field. That would make searching far easier.

 

You may need REGEX() function for the foo% problem (but I'm useless at those) or search for "foo,%" but then youd have to guarantee the last keyword in each record had a comma following it.

 

As for time, try both ways, getting microtime() at beginning and end and checking difference.

Link to comment
Share on other sites

I'd redesign the table so you had a keyword table, each row with a single keyword + id field. That would make searching far easier.

You mean just a TABLE devoted entirely to "keywords". And then another table with all my other data?

 

So table KEYWORD would look like this

id  |  keywords

 

and table CUES would look like this

id | name  | composer | time | demo | saved

 

is that what you mean?

Link to comment
Share on other sites

[pre]

ID| KEYWORD

--+-----------

1 | monkey              -+

1 | sad                  |

1 | foo                  +-- 5 keywords for id = 1

1 | mustard              |

1 | Ron                -+

 

2 | foodinkle          -+                       

2 | Ron                  |                       

2 | mud                  +-- 5 keywords for id = 2

2 | mudd                |                       

2 | sad                -+                       

[/pre]

Link to comment
Share on other sites

  • 3 weeks later...

Hey again....long time but I'm still working on it. I've been looking on the web, and I can't see how to run the SQL command of CREATE TEMPORARY TABLE tmp_cues

 

Here is why my codes looks like now (oh by the way, thanks for the RegEx hit!)

$search = "two words";
$sql = "CREATE TEMPORARY TABLE tmp_cues";
mysql_query($sql);
$sql = "SELECT id, url, name, composer, time, description FROM cues WHERE keywords REGEXP '([,;. ]|^)+$search([,;. ]|$)+'";
$result = mysql_query($sql) or die (mysql_error());

$sql = "SELECT id, COUNT(*) as t FROM tmp_cues GROUP BY id ORDER BY t DESC";
$result = mysql_query($sql) or die (mysql_error());

header("Content-Type: application/xml; charset=ISO-8859-1");
echo '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n";
echo '<matches>' . "\n";
while($row = mysql_fetch_array($result))
{
echo "\t" .   '<cue id="' . $row['id'] . '">' .  "\n";
echo "\t\t" . '<url>' . $row['url'] . '</url>' . "\n";
echo "\t\t" . '<name>' . $row['name'] . '</name>' . "\n";
echo "\t\t" . '<composer>' . $row['composer'] . '</composer>' . "\n";
echo "\t\t" . '<time>' . $row['time'] . '</time>' . "\n";
echo "\t\t" . '<description>' . $row['description'] . '</description>' . "\n";
echo "\t" .   '</cue>' . "\n\n"; 
}

echo '</matches>';

 

Error message: Table 'digit.tmp_cues' doesn't exist

 

 

but if I concatinate the sql's I get this:

Warning:  mysql_fetch_array(): supplied argument is not a valid MySQL result resource in C:\Program Files\xampp\xampp\htdocs\test.php on line 26

Link to comment
Share on other sites

Never mind....I don't know how I fixed it but I got 1 final problem. WHOO HOO!!!!

 

The data isn't sorted:

// search word
$search = "sad";
$search2 = "two words";




/*
* SQL QUERIES
*/

// put data into temporary table
$sql = "CREATE TEMPORARY TABLE tmp_cues";
$sql .= " SELECT id, url, name, composer, time, description FROM cues WHERE keywords REGEXP '([,;. ]|^)+$search([,;. ]|$)+'";
$sql .= " UNION";
$sql .= " SELECT id, url, name, composer, time, description FROM cues WHERE keywords REGEXP '([,;. ]|^)+$search2([,;. ]|$)+'";
$result = mysql_query($sql) or die (mysql_error());

// get date from temporary table and sort
$sql = " SELECT id, url, name, composer, time, description, COUNT(*) as t FROM tmp_cues GROUP BY id ORDER BY t DESC";
$result = mysql_query($sql) or die (mysql_error());




/*
* ECHO DATA OUT TO SCREEN
*/
header("Content-Type: application/xml; charset=ISO-8859-1");
echo '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n";
echo '<matches>' . "\n";
while($row = mysql_fetch_array($result))
{
echo "\t" .   '<cue id="' . $row['id'] . '">' .  "\n";
echo "\t\t" . '<url>' . $row['url'] . '</url>' . "\n";
echo "\t\t" . '<name>' . $row['name'] . '</name>' . "\n";
echo "\t\t" . '<composer>' . $row['composer'] . '</composer>' . "\n";
echo "\t\t" . '<time>' . $row['time'] . '</time>' . "\n";
echo "\t\t" . '<description>' . $row['description'] . '</description>' . "\n";
echo "\t" .   '</cue>' . "\n\n"; 
}

echo '</matches>';

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.