mysql - check if a group of elements are included in another group - php

I have the following setup:
An array in php like this:
$arr = array(1, 2, 3, 4);
A query that looks like this:
SELECT `epicThing` FROM `epicTable` AS `epic`
WHERE
SELECT `ids` FROM `someTable`
WHERE `epic`.`somethingSomething` = `someTable`.`somethingElse`
(<<<< HERE IS MY PROBLEM >>>>)
The subquery returns something like (1, 2, 3, 4, 5, 6, 7, 8, 9).
Now what I need to check is that each of the elements from the array is in that returned answer of the subquery.
Basically something like
SELECT `epicThing` FROM `epicTable` AS `epic`
WHERE
'1' IN (
SELECT `ids` FROM `someTable`
WHERE `epic`.`somethingSomething` = `someTable`.`somethingElse`
)
AND
'2' IN (
SELECT `ids` FROM `someTable`
WHERE `epic`.`somethingSomething` = `someTable`.`somethingElse`
)
AND
'3' IN (
SELECT `ids` FROM `someTable`
WHERE `epic`.`somethingSomething` = `someTable`.`somethingElse`
).......
But for each element.
For simplicity let's assume that elements are always in order (because I will probably need to convert the array to string), if is not possible otherwise. But I would prefer a general solution if available.
What I DON'T want to do is to get data in php and check it there (this is only a really really small part of a huge query).

If I'm understanding your question correctly, I think this would be the easiest way for you to test that all IDs in your array match to a record in the database:
<?php
$myArray = array(1,2,3);
$myArrayCount = count($myArray);
// Convert array for the query
$queryArray = implode(",", $myArray);
SELECT COUNT(DISTINCT(YourTable.id)) AS count
FROM YourTable
WHERE YourTable.id IN ($queryArray)
HAVING count = $myArrayCount;
?>
Mysql will return empty results if the HAVING count = $myArrayCount; does not match the number of IDs you are checking for.

Related

Compare values of a PHP array with a large table MySQL

Ok, normally I would do something like this in PHP if I compared just few values:
// I want to get 1
$a = array(1,2);
$b = array(2);
// It produces 1
$result = array_diff($a, $b);
But in this case, $b is a large table in MySQL with millions of rows and retrieving it to PHP would be crazy, so my DBMS (MySQL) must do the work.
How could I do something like:
-- I need treating $a as a column
SELECT $a NOT IN (SELECT id FROM b);
Example
table B
|id|
2
3
4
array A
array(1, 2, 3, 5);
Result
A - B = A - INTERSECT(A,B) = [1, 5]
Example 2
This is exactly what I need for SQL server. Any ideas to do something similar in MySQL?
Note: A has about 5000 ids, so:
SELECT 1
UNION SELECT 1
UNION SELECT 1
UNION SELECT 2
UNION SELECT 5
...
...produces #1064 - memory exhausted
You can join the variables in the array $a in PHP and use that in your SQL query to retrieve the data, It would efficient in you case.
$in = join(',', array_fill(0, count($a), '?'));
$sql = "
SELECT *
FROM galleries
WHERE id IN ($in)"
Here is a working fiddle to prove that the SQL query will return the desired output.
EDIT :
According your new requirement, You could do the array comparison in
the PHP side because You have to somehow bring up the result from
MySQL to eliminate the result from PHP array. If you retrieve the
array $a from another table then we could have done something like a
join. But in this case we cannot do it. Also you mentioned that the
MySQL table has large number of rows so I assume PHP array will anyway
remove only couple of items from the results after bringing it to the
memory.
If you want to check the values exist or not, you can try this one
<?php
$some_id = "100";
$id = mysql_real_escape_string($some_id); // i use escape to compare IP ADDRESSES. you can remove it
$result = mysql_query("SELECT id FROM your_table WHERE id = '$id'");
if (!mysql_num_rows($result))
{
echo "Not Exists";
}
else
{
echo "Exists";
}
?>
I hope this will help
Consider using the JOIN NULL query:
strSQL = "SELECT t2.id
FROM tableB t1
RIGHT JOIN
(SELECT id
FROM tableB
WHERE id IN (".implode(',',$arrayA).")
) t2
ON t1.id = t2.id
WHERE t1.id IS NULL";
Also, depending on how large $arrayA is, consider appending to temp table and join above, replacing sub query with temp table.

PHP variable variables with mysql resultset

So I have a mysql table which has a id column (sid) that can be dynamically added to. Now I am doing a query to get count of all entries grouped into each of these sid's like so:
SELECT SUM(IF(sid = 71, 1, 0)) as count71,
SUM(IF(sid = 72, 1, 0)) as count72,
SUM(IF(sid = 75, 1, 0)) as count75,
SUM(IF(sid = 81, 1, 0)) as count85
FROM `table`
WHERE userid=44;
Note that all the SUM fields are created dynamically and I don't know what the actual sid's are. Now question is how do I loop through the resultset for each of the counts using PHP's variable variables? I've tried this but doesn't work.
$count_var = "rs['count71']"
$$count_var // holds number of entries where sid is 71;
Thanks!
May I suggest this instead:
select sid, count(*) from `table` where userid = 44 group by sid ;
You could do:
$count_var = "rs['count71']";
echo eval('return $'. $count_var . ';');
but of course #troelskn's answer is probably the best solution for what you want

Select values that are NOT in table

Let's say I have three values in PHP: "a", "b", "c". Doesn't matter whether in an array or comma separated string.
There is a table in database:
id | value
1 | a
2 | b
3 | d
My purpose is to find the values that are in php array but not in database table.
The given example will give "c".
Can I do it with only one query?
UPDATE
Received several good suggestions in answers about array_diff(), though in my case the DB table is really large and the array has not more than 5-6 items. So it would be better to perform 5-6 queries, I think.
If the PHP array is short, you can build a UNION ALL query to build your small table, then use NOT IN or LEFT JOIN query (whichever is faster) against the large table:
SELECT value
FROM (
SELECT 'a' AS value
UNION ALL
SELECT 'b'
UNION ALL
SELECT 'c'
) AS php_array_values
WHERE value NOT IN (
SELECT value
FROM that_large_table
);
Alternately, you can insert the php array values in a temporary table and use the IN or JOIN queries. Of course, this means you end up writing three extra queries:
CREATE TEMPORARY TABLE IF NOT EXISTS php_array_values (value VARCHAR(100));
DELETE FROM php_array_values;
INSERT INTO php_array_values VALUES ('a'), ('b'), ('c');
SELECT php_array_values.value
FROM php_array_values
LEFT JOIN that_large_table ON php_array_values.value = that_large_table.value
WHERE that_large_table.value IS NULL
how about this?
<?php
$a = array('a', 'b', 'c');
$values = implode("','", $a);
$sql = "SELECT DISTINCT `value` FROM `mytable` WHERE `value` IN ('$values')";
echo $sql;
perform the sql query. the result will be those 0 to 3 elements you already have. next, do an array_diff (which will not be heavy at all, since you'll have your initial small array, and the array of those in the db, which is even smaller).
$not_in_db = array_diff($a, $array_from_sql_result);
if what you have is a string with comma separated values, then you'll need to "explode" it first:
$s = "a,b,c";
$a = explode(",", $s);
You could select all the entries in the table and then perform an array_diff().
But this isn't one query, is one query and some post processing.
For this I would pull values from the table into an array and use array_diff
REF: http://www.php.net/manual/en/function.array-diff.php
Instead of pulling all the elements from the DB you can try using 'LIKE' statement, this will reduce the number of entries pulled from DB.
something like this :
PHP array values : a,b,c
DB values : a,b,d
select value from your_table_name where (value LIKE '%a%') OR (value LIKE '%b%') OR (value LIKE '%c%');
o/p of this will be : {a,b}
now use array_diff of php.
select max(*) as count from tablename
where field1 != $arr[0] && field2 != $arr[1] && field3 != $arr[2];
You can use and or or operators if you want. if the return count for this query is 0 then the array values are not exist in the database already.

sort an $array of ints by repetition and remove repetitions

i need to do this in php
lets say i have [1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,4,5,5,5,5,5,5,5,5,5,5,5,9,9,9,9,9]
i would like [1,5,9,2,3,4]
but my situation its a bit different, it's result from a mysql query
i have only an asociative atribute 'id_deseada', so i do now
while($row = mysql_fetch_array($result){
$t = $row['id_deseada'];
}
so instead of that, i guess i'd have to do domething like the first example; sort $result ordered by times of repetition and maybe beetter in a new array with a new field 'count' ?
This all begins because of this query:
SELECT articles.id as id_deseada,tags.* FROM articles,tags WHERE tags.id_article = articles.id AND tags.name IN ('name one','name two','form search inputs','...)
the problem is that returns one result for every tag and i want on result for every article..
First, generate the value array like this:
$vals = array();
while($row = mysql_fetch_array($result){
$vals[] = $row['id_deseada'];
}
Then, count and sort:
$valCounts = array_count_values($vals);
arsort($valCounts);
$result = array_keys($valCounts);
You can actually do it using an SQL query. For example, we have this table:
create table lol (id_deseada int);
insert into lol values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(2),(3),(4),(5),(5),(5),(5),(5),(5),(5),(5),(5),(5),(5),(9),(9),(9),(9),(9);
You can select the id_deseada's from the database sorting by repetitions by using grouping and ordering.
SELECT id_deseada FROM lol
GROUP BY id_deseada
ORDER BY COUNT(*) DESC
Result: 1, 5, 9, 2, 3, 4.

Selecting large amount of rows from database table with MySQL

I have a table with attributes like this:
likes(id, message, ip, time)
id is the primary key and is auto-incrementing. Whet I want to do is select 30 rows from this table based on an id that I provide.
I can build a random array of all IDs I want to grab from the table, now I just need to go about doing that. My usual SQL query would be:
SELECT message
FROM `likes`
WHERE id=$id
LIMIT 1
But I need to select 30 rows. There are two ways I can do this, I can either use a FOR loop with 30 queries, or combine it all into one query and grab them all at the same time. Obviously I would like to do the latter.
Can anyone help me out on the SQL query to use to grab more than one row from my database table at once? And perhaps an example of how I would parse these into an array for easy retrieval?
Greatly appreciated, thanks.
You could use the IN operator, so it would be something like this:
SELECT message FROM likes WHERE id IN (1, 2, 3, 4, 5, ...)
$ids = array(1,2,3,4,5,6,7,8,9); //or however many
$query = "SELECT * FROM `likes` WHERE `id` IN (".implode(', ', $ids).")";
$res = mysql_query($query);
$results = array();
while($tmp = mysql_fetch_array($res)) {
$results[$tmp['id'] = $tmp;
}
Will give you an array, $results, sorted by key ['id'], with each being an array on each answer key-- 'id', 'message', 'ip', 'time'. So for example:
for($results as $key => $val) {
echo "${val['ip']} posted {$var['message']} on {$val['time']} <br/>";
}

Categories