MYSQL select display matching and non matching records - php

I have a list of strings all separated by a new line. I need to match these strings with the value in a column in one single table. The problem is I need to display non-matching records as a defined value, example "not found" so the output remains the same length as the input and the results all remain in the same order.
Example Input
apple
orange
pear
banana
Desired Output
apple exists
orange not found
pear exists
banana exists
Is it possible to assign a custom value to records not found as well as display records found in a single statement?
Info seems to suggest I can create a statement using IFNULL to return non-matching records, I have experimented with this but to no avail.
<?php
// Wrap strings for select statement
$strings = $_POST['mystrings'];
$regex = '~<[^>]+>(*SKIP)(*FAIL)|\b\w+\b~';
$strings_wrapped = preg_replace($regex, "'\\0',", $strings);
$strings_prepared = substr($strings_wrapped, 0, -1);
// Statement
$select = "select * from table where specific_row in ($strings_prepared)";
// Connect
$connect = mysqli_query($con, $select);
// Retrieve rows
while ($row=mysqli_fetch_array($connect)) {
$column1 = $row['column1'];
$column2 = $row['column2'];
$column3 = $row['column3'];
$column4 = $row['column4'];
$column5 = $row['column5'];
// Display results
$results = "$column1-$column2-$column3-$column4-$column5\n";
echo $results;
}
?>
The matching rows are returned without error. I just don't know how to display the non-matching rows as well.

This is the approach you can use:
// Statement
$select = "select * from table where specific_row in ($strings_prepared)";
// Connect
$connect = mysqli_query($con, $select);
// Retrieve rows
$founded = [];
while ($row = mysqli_fetch_array($connect)) {
$founded[$row['specific_row']] = $row['column1']; // or whatever
}
foreach ($strings_prepared as $string) {
if (!empty($founded[$string])) {
echo 'found';
} else {
echo 'NOT found';
}
}

You can use a subquery to create a derived table containing the names you want to search for, and join that with the table.
SELECT a.value, IF(b.specific_row IS NULL, 'not found', 'exists') AS found
FROM (
SELECT 'apple' AS value
UNION
SELECT 'orange'
UNION
SELECT 'pear'
UNION
SELECT 'banana'
) AS a
LEFT JOIN table AS b ON a.value = b.specific_row

Related

How to ignore duplicate rows in foreach loop when retrieve the data from database by MYSQL

I have got the following code to find the similar keywords in body of a text and display the related links with same keyword.
But the problem is for example if two keywords are in row 2 body, Row 2 displays two times but I need the row 2 is displayed once. I tried SELECT DISTINCT but it does not work in foreach loop correctly.
$tags2=explode(",",$tags);
foreach ($tags2 as $i) {
$cat_sqlii="SELECT DISTINCT id, source,title,summary,newsText,photo,mainphoto,link,Date,tags FROM newxtext WHERE (newsText LIKE '%$i%')";
$cat_sql_queryii=mysqli_query($con,$cat_sqlii);
$cat_sql_rowii=mysqli_fetch_assoc($cat_sql_queryii);
do{
echo $cat_sql_rowii['id'].'<br/>';
}while($cat_sql_rowii=mysqli_fetch_assoc($cat_sql_queryii));
}
Just do one query that tests for any of the tags using OR.
$patterns = array();
foreach ($tag in explode(',', $tags)) {
$patterns[] = "newstext like '%$tag%'";
}
$where = implode(' OR ', $patterns);
$cat_sqlii="SELECT id, source,title,summary,newsText,photo,mainphoto,link,Date,tags
FROM newxtext
WHERE ($where)";
$cat_sql_queryii=mysqli_query($con,$cat_sqlii);
while ($cat_sql_rowii = mysqli_fetch_assoc($cat_sql_queryii)) {
echo $cat_sql_rowii['id'].'<br/>';
}
Another approach could be using a temporary table receiving the results for each iteration and querying that table in the end:
mysqli_query($con, "CREATE TEMPORARY TABLE tmpSearchResults(id int primary key) ENGINE=Memory");
$tags2=explode(",",$tags);
foreach ($tags2 as $i) {
$insertToTemp ="INSERT INTO tmpSearchResults
SELECT id
FROM newxtext
WHERE (newsText LIKE '%$i%')";
mysqli_query($con,$insertToTemp);
}
$queryFromTemp = "SELECT DISTINCT n.id, n.source,n.title,n.summary,n.newsText,n.photo,n.mainphoto,n.link,n.`Date`,n.tags
FROM tmpSearchResult r
JOIN newxtext n
WHERE r.id = n.id";
$resultSet = mysqli_query($con,$queryFromTemp);
while($data = mysqli_fetch_assoc($resultSet)){
// ... process here
}
mysqli_free_result($resultSet);
When you close the connection, the temporary table will be dropped automatically.
If you expect huge search results, consider using another storage engine than MEMORY for the temptable.

How to get name from id in array using query?

I had array values as cause
Ex: $cause = $_REQUEST['cause'];
ie., $cause = 2,3,4
How to get that array value cause name from query
My table name is 'cp_cause'
How to get the 2,3,4 cause name from the above table.
My sample query model in thinkphp is
$cause_name = $GLOBALS['db']->getAll("select category from ".DB_PREFIX."category where id = '".$cause."'");
i want the name of labour, health, women
If I get it right: you get comma separated Ids and want to query this?
SELECT * FROM cp_cause WHERE id IN (2, 3, 4)
PHP:
$cpCauses = $GLOBALS['db']->getAll("select * from cp_cause where id in('".$cause."')");
The result should be a list, containing the matching rows. But we do not know, what your getAll-Method returns!
Example: if result is an array, you can iterate:
foreach($cpCauses as $cause) {
echo $cause['cause_name'];
}
You need to create string like '2','3','4' for checking with MySql in clause.
For e.g.
<?php
$cause = array();
$cause[] = '2';
$cause[] = '3';
$cause[] = '4';
$sql_where = array();
foreach($cause as $values){
$sql_where[] = "'".$values."'";
}
$sql_where = implode(",",$sql_where);
$cause_name = $GLOBALS['db']->getAll("select category from ".DB_PREFIX."category where id in '".$sql_where."'");
?>

PHP inserting array into an object

I am trying to inject an array into an object but it's just not working. This is what I am doing:
1) Get a specific Match record from the database
2) Get all the Player records from the database that are associated with that match
3) Add them players to the Match object
Code:
$matchQuery = "SELECT * FROM matches where new = 1 order by date asc limit 1";
$matchResult = mysql_query($matchQuery,$link) or die('Errant query: '.$matchQuery);
/* create one master array of the records */
$matches = array();
if(mysql_num_rows($matchResult)) {
while($match = mysql_fetch_assoc($matchResult)) {
$playersQuery = "SELECT p.* FROM match_players mp
LEFT JOIN players p on p.id = mp.player_id
WHERE mp.match_id = '$match->id'";
$playerResult = mysql_query($playersQuery,$link) or die('Errant query: '.$playersQuery);
$players = array();
if(mysql_num_rows($playerResult)) {
while($player = mysql_fetch_assoc($playerResult)) {
$match->players[] = $player; //<-- This doesn't seem to work
}
}
$matches[] = $match;
}
}
The objects within Match are being spat out, BUT, the Players are not.
$match is an array, the result of the deprecated mysql_fetch_assoc(). So $match->players[] = $player; is not going to work.
If there is no players key in the sql result, you can add it to the array:
$match['players'][] = $player;
Otherwise you would have to use a different key.
Another problem is your query in the loop: You use $match->id and that should be $match['id'] as $match is an array.
By the way, doing sql queries in a loop is never a good idea, you should try to get your results in one query joining the different tables.
$match["players"] = array();
while($player = mysql_fetch_assoc($playerResult)) {
$match["players"][] = $player;
}

Find duplicate rows in mysql simplified example

Confession: a mysql newb requires simple example to locate duplicate rows in somewhat large table. I have searched for and read many other threads with similar titles, but the examples are so complex that I cannot apply them to my basic situation.
A MySQL table has only 5 fields, but there are hundreds of rows. I wish to locate duplicate rows -- I know there is one for sure and wonder if there are others.
Example Row: (rel_id is auto-incrementing, primary key field)
'rel_id' => 1
'host' => 17
'host_type' => 'client'
'rep' => 7
'rep_type => 'cli_mgr'
My approach was to:
1. Read entire table into mysql query
2. row-by-row compare the 4 data fields to those of previous ("done") rows
3. after comparing a "new" row, append it to array of "done" rows
Here is what I have tried. I am sure that there must be a much simpler solution. You will see that I am bogged down in trying to append the "new" row to the array of "done" rows:
$rRels = mysql_query("SELECT * FROM `rels`");
$a = array();
$e = array();
$c1 = 0;
$c2 = 0;
While ($r = mysql_fetch_assoc($rRels)) {
$i = $r['rel_id'];
$h = $r['host'];
$ht = $r['host_type'];
$r = $r['rep'];
$rt = $r['rep_type'];
foreach($a as $row) {
$xh = $row['host'];
$xht = $row['host_type'];
$xr = $row['rel'];
$xrt = $row['rel_type'];
if (($h==$xh) && ($ht==$xht) && ($r==$xr) && ($rt==$xrt)) {
echo 'Found one<br>';
$e[] = $r;
}
$c2++;
}
$a = array_merge(array('rel_id'=>$i, 'host'=>$h, 'host_type'=>$ht, 'rep'=>$r, 'rep_type'=>$rt), $a);
$c1++;
}
echo '<h3>Duplicate Rows:</h3>';
foreach ($e as $row) {
print_r($row);
echo '<br>';
}
echo '<br><br>';
echo 'Counter 1: ' . $c1 . '<br>';
echo 'Counter 2: ' . $c2 . '<br>';
This should do the trick:
SELECT COUNT(*) as cnt, GROUP_CONCAT(rel_id) AS ids
FROM rels
GROUP BY host, host_type, rep, rep_type
HAVING cnt > 1
any "duplicate" records will have a cnt > 1, and the group_concat will give you the ids of the duped records.
Pure no-php solution : to make the copy of the old table (named oldTable) , with no data
create table newTable like oldTable;
Modify the structure to prevent duplicates and add unique key over all 5 columns.
alter table newTable add unique index(rel_id,host,host_type,rep,rep_type );
Then whith sql query copy the rows from oldTable
insert IGNORE into newTable select * from oldTable
In newTable you have only the unique data.
Another option is group by, if you will get the number of duplicate rows use
select concat_ws('_',rel_id,host,host_type,rep,rep_type) as str, count(*)
from oldTable
group by str
You can this query to find all the duplicate rows. Hopefully, it should be easy integrating in your PHP code.
// This will give you all the duplicates
// Self join where all the columns have the same values but different primary keys
SELECT *
FROM rels t1, rels t2
WHERE t1.rel_id != t2.rel_id
AND t1.host = t2.host
AND t1.host_type = t2.host_type
AND t1.rep = t2.rep
AND t1.rep_type = t2.rep_type
Finding duplicates is more easily done in SQL than in PHP.
SELECT GROUP_CONCAT(rel_id)
FROM rels
GROUP BY host, host_type, rep, rep_type HAVING COUNT(rel_id)>1;
This will show the groups of rel_id that point to identical records. The HAVING COUNT(rel_id)>1 clause allows us to skip unduplicated records.

Getting results from 2 consecutive queries (PHP, SQL)

I need to return data from 2 separate tables at the same time. The info I need from the 2nd table is determined by what is returned from the first table. Here's what I'm working with..
$query = "SELECT * FROM pending WHERE paymentid = '".$_GET['vnum']."'";
$result = mysql_query($query);
$num = #mysql_num_rows($result);
$linkid = $res['paymentid'];
if ($num==0) {
echo "Hello, ".$_SESSION['Fname']."<br />There was an error, I cannot find this payment in the records.";
} else {
$picquery = mysql_query("SELECT * FROM _uploads_log WHERE linkid = '".$linkid."'");
$numb = #mysql_num_rows($picquery);
if ($numb==0) {
echo "there is no picture"; }
else {
echo "<img src=\"".$res['log_filename']."\" width=\"100\">"; }
I don't understand how to return the results as an array, if $res[] returns the results for the first query, then what returns the results for the second one?
or is there a better way to do this entirely?
Thank you
You need to do a join, but in order to still get results from your first query even if there is no picture (I assume that's why you split it up) you want a left join.
select * from pending left join _uploads_log on pending.paymentID=$_GET['vnum'] and _uploads_log.linkid = pending.paymentID
(note: php markings removed for readability - you'll have to add them back in)
This should (untested since I don't have your tables) return the full row for your vnum variable and also include the picture data if there is one.

Categories