The user can search for something using select and checkbox forms. The data is sent in GET variables.
I'm collected all the possible values in variables and putting it into an array:
$term_taxomony_ids_array = array($term_taxonomy_id_m, $term_taxonomy_id_l, $term_taxonomy_id_t_1, $term_taxonomy_id_t_2, $term_taxonomy_id_t_3, $term_taxonomy_id_t_4, $term_taxonomy_id_t_5, $term_taxonomy_id_t_6, $term_taxonomy_id_t_7, $term_taxonomy_id_t_8);
print_r($term_taxomony_ids_array); would then give
eg:
Array (
[0] => 12
[1] => 14
[2] =>
[3] =>
[4] => 9
[5] =>
[6] => 2
[7] =>
[8] =>
[9] =>
)
How would I make this array simpler but leaving out the empty results altogether (as suggested in a comment)?
I need to find the 'places' in the database who match all the criteria that was selected.
My database table is set up so I have two columns.
1. Object_id 2. term_taxonomy_id.
The term_taxonomy_id are the values in the array.
eg my table looks like this
Object id term_taxonomy_id
2 12
2 3
3 12
3 14
3 9
3 2
4 5
5 9
So only object_id '3' matches all the terms in the array - 12, 14, 9, 2
How would I run a query to find this result?
I'm using a mysql database, phpmyadmin and my site is built on wordpress.
Thanks
Basically:
SELECT objectID, COUNT(term_taxonomy_id) AS cnt
FROM yourtable
WHERE term_taxonomy_id IN (2, 9, 14, 12)
GROUP BY objectID
HAVING cnt = 4
find all the objectIDs that have one or more matching taxonomy IDs, but then return only the object IDs that have FOUR matching taxonomy IDs.
Use IN, Combined with COUNT() and having/GROUP.
$array = array_filter(array_unique($array));
$count = count($array);
$sql = "SELECT id, COUNT(*) FROM table WHERE field IN (" . implode(',', $array) . ") GROUP BY id HAVING COUNT(*) = " . $count;
The SQL might be a bit off (you might have to re-order having and group).
Related
I hope someone is able to help me with the problem I'm facing for hours already. I'm trying to built a MySQL INSERT from two arrays. One array ($bms) holds 6 values and the second one holds 3 values (I want to use the array with 3 values inside the INSERT query where I'm using the placeholder group right now). Each value of the (group array) needs to be used 2 times. I hope you understand with my example below:
The 2 arrays – always include 6 respectively 3 values:
Array ( [0] => 8 [1] => 3 [2] => 4 [3] => 121 [4] => 13 [5] => 154 ) // $bms
Array ( [0] => 266 [1] => 267 [2] => 268 ) // group
The query with foreach loops:
$query = "INSERT INTO userlinks (linkpool_id, group, userid) VALUES ";
foreach($bms as $bm) {
$query .= "('".$bm."', group, '".$userid."'),";
}
echo $query;
The output so far:
INSERT INTO userlinks (linkpool_id, group, userid) VALUES ('8', group, '19'),('3', group, '19'),('4', group, '19'),('121', group, '19'),('13', group, '19'),('154', group, '19')
WHAT I'M TRYING TO ACHIEVE:
INSERT INTO userlinks (linkpool_id, group, userid) VALUES ('8', '266', '19'),('3', '266', '19'),('4', '267', '19'),('121', '267', '19'),('13', '268', '19'),('154', '268', '19')
I really appreciate your help and invested time – awesome community!
You can use a for loop instead :
$query = "INSERT INTO userlinks (linkpool_id, group, userid) VALUES ";
for($i = 0; $i < count($bms); $i++) {
$j = (int) $i/2; //[0,1] will return 0, [2,3] return 1 etc...
$query .= "('".$bms[$i]."', '".$groups[$j]."', '".$userid."'),";
}
rtrim($query, ",");
echo $query;
Edit: Thanks #RajdeepPaul for more precision.
I’ve seen the following question on StackOverflow, Intelligent MySQL GROUP BY for Activity Streams posted by Christian Owens 12/12/12.
So I decided to try out the same approach, make two tables similar to those of his. And then I pretty much copied his query which I do understand.
This is what I get out from my sandbox:
Array
(
[0] => Array
(
[id] => 0
[user_id] => 1
[action] => published_post
[object_id] => 776286559146635
[object_type] => post
[stream_date] => 2015-11-24 12:28:09
[rows_in_group] => 1
[in_collection] => 0
)
)
I am curious, since looking at the results in Owens question, I am not able to fully get something, and does he perform additional queries to grab the actual metadata? And if yes, does this mean that one can do it from that single query or does one need to run different optimized sub-queries and then loop through the arrays of data to render the stream itself.
Thanks a lot in advanced.
Array
(
[0] => Array
(
[id] => 0
[user_id] => 1
[fullname] => David Anderson
[action] => hearted
[object_id] => array (
[id] => 3438983
[title] => Grand Theft Auto
[Category] => Games
)
[object_type] => product
[stream_date] => 2015-11-24 12:28:09
[rows_in_group] => 1
[in_collection] => 1
)
)
In "pseudo" code you need something like this
$result = $pdo->query('
SELECT stream.*,
object.*,
COUNT(stream.id) AS rows_in_group,
GROUP_CONCAT(stream.id) AS in_collection
FROM stream
INNER JOIN follows ON stream.user_id = follows.following_user
LEFT JOIN object ON stream.object_id = object.id
WHERE follows.user_id = '0'
GROUP BY stream.user_id,
stream.verb,
stream.object_id,
stream.type,
date(stream.stream_date)
ORDER BY stream.stream_date DESC
');
then parse the result and convert it in php
$data = array(); // this will store the end result
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
// here for each row you get the keys and put it in a sub-array
// first copy the selected `object` data into a sub array
$row['object_data']['id'] = $row['object.id'];
$row['object_data']['title'] = $row['object.title'];
// remove the flat selected keys
unset($row['object.id']);
unset($row['object.title']);
...
$data[] = $row; // move to the desired array
}
you should get
Array
(
[0] => Array
(
[id] => 0
[user_id] => 1
[fullname] => David Anderson
[verb] => hearted
[object_data] => array (
[id] => 3438983
[title] => Grand Theft Auto
[Category] => Games
)
[type] => product
[stream_date] => 2015-11-24 12:28:09
[rows_in_group] => 1
[in_collection] => 1
)
)
It seems that you want a query where you can return the data you're actually able to get plus the user fullname and the data related to the object_id.
I think that the best effort would be to include some subqueries in your query to extract these data:
Fullname: something like (SELECT fullname FROM users WHERE id = stream.user_id) AS fullname... or some modified version using the stream.user_id, as we can't identify in your schema where this fullname comes from;
Object Data: something like (SELECT CONCAT_WS(';', id, title, category_name) FROM objects WHERE id = stream.object_id) AS object_data. Just as the fullname, we can't identify in your schema where these object data comes from, but I'm assuming it's an objects table.
One object may have just one title and may have just one category. In this case, the Object Data subquery works great. I don't think an object can have more than one title, but it's possible to have more than one category. In this case, you should GROUP_CONCAT the category names and take one of the two paths:
Replace the category_name in the CONCAT_WS for the GROUP_CONCAT of all categories names;
Select a new column categories (just a name suggestion) with the subquery which GROUP_CONCAT all categories names;
If your tables were like te first two points of my answer, a query like this may select the data, just needing a proper parse (split) in PHP:
SELECT
MAX(stream.id) as id,
stream.user_id,
(select fullname from users where id = stream.user_id) as fullname,
stream.verb,
stream.object_id,
(select concat_ws(';', id, title, category_name) from objects where id = stream.object_id) as object_data,
stream.type,
date(stream.stream_date) as stream_date,
COUNT(stream.id) AS rows_in_group,
GROUP_CONCAT(stream.id) AS in_collection
FROM stream
INNER JOIN follows ON 1=1
AND stream.user_id = follows.following_user
WHERE 1=1
AND follows.user_id = '0'
GROUP BY
stream.user_id,
stream.verb,
stream.object_id,
stream.type,
date(stream.stream_date)
ORDER BY stream.stream_date DESC;
In ANSI SQL you can't reference columns not listed in your GROUP BY, unless they're in aggregate functions. So, I included the id as an aggregation.
This question already has answers here:
MySQL query to return results in specific order without order by
(5 answers)
Closed 8 years ago.
I have a simple mysql query like this.
SELECT name,cat_id FROM table WHERE cat_id IN (67,65,66);
But I am having a problem getting the results back in a proper order.
[0] => Array
(
[cat_name] => name 1
[cat_id] => 65
)
[1] => Array
(
[cat_name] => name 2
[cat_id] => 66
)
[2] => Array
(
[cat_name] => name 3
[cat_id] => 67
)
I need them to be ordered by the cat_id that was put into the sql statement.
67, then 65 and then 66.
But it always wants to return results by order 65, 66, 67.
Can someone help me figure this out? I rather get the results in the correct order, than use php to manipulate the array.
SELECT
name,
cat_id
FROM table
WHERE cat_id IN (67)
order by cat_id asc;
UNION
SELECT
name,
cat_id
FROM table
WHERE cat_id IN (65,66)
order by cat_id asc;
EDIT
solved ! it was my fault, the mysql query and the php method, both are working perfectly. my very bad example cunfused myself. aktually they should be sorting products by favorite ( true / false ) and then by date.
i'm trying to sort a multidimensional array by two "cols" but it just won't work for me :O
I've serched and copyed all possible ways ( mysql - order by, php - array_multisort() )
but it still won't work for me....
here is the method i've tryed first:
// MySQL Query
SELECT * FROM `test` ORDER BY `name` ASC, `age` DESC;
// or
SELECT * FROM `test` ORDER BY `name`, `age`;
// or
SELECT * FROM `test` ORDER BY name, age;
// or
SELECT * FROM `test` ORDER BY name, age DECT;
// `name` is VARCHAR and `age` is INT
so , i've tryed all possible syntax, but the query wont give me the wanted result.
the original table :
ID NAME AGE
---------------------
1 adam 23
2 bernd 30
3 cris 22
4 dora 21
5 anton 18
6 brad 36
7 sam 41
8 ali 13
what i want to get from MySQP Query :
ID NAME AGE
--------------------- // first sort by name...
8 ali 13 // then sort by age
5 anton 18 // ...
1 adam 23 // for each "similar" name or names with "a", "b", ...
2 bernd 30 // and so on...
6 brad 36
3 cris 22
4 dora 21
7 sam 41
but it actually gives my either sorted by NAME ( ORDER BY name, age ) or AGE ( ORDER BY age, name;
as i get frustrated, i've decidet to just get that query and sort it in PHP...
well, i've also tryed some codes but they all don't work either.
here is the one i aktually did now:
// this array is just exported from mysql to debug without mysql query...
$test = array(
array('id' => '1','name' => 'adam','age' => '23'),
array('id' => '2','name' => 'bernd','age' => '30'),
array('id' => '3','name' => 'cris','age' => '22'),
array('id' => '4','name' => 'dora','age' => '21'),
array('id' => '5','name' => 'anton','age' => '18'),
array('id' => '6','name' => 'brad','age' => '36'),
array('id' => '7','name' => 'sam','age' => '50'),
array('id' => '8','name' => 'ali','age' => '13')
);
// ...print out the original array
foreach( $test as $key => $value ) {
echo $value['name'] . " - " . $value['age'] . "<br>";
}
// here is the part where i am sorting...
$sort = array();
foreach ($test as $key => $value ) {
$sort['name'][$key] = $value['name'];
$sort['age'][$key] = $value['age'];
}
array_multisort($sort['age'], SORT_ASC, $sort['name'], SORT_DESC, $test);
// ...till here.
// reorder array and print the new sorted array
$sorted = array();
for( $i = 0; $i < count( $sort['name'] ); $i++ ) {
array_push( $sorted, array( $sort['name'][$i], $sort['age'][$i] ) );
echo $sort['name'][$i] . " - " . $sort['age'][$i] . "<br>";
}
but as you'll see if you test this, the sorting will just affect the AGE...
i dont know what i am doing wrong, prease tell me guys T_T
It appears to me that you only want to sort on the first char of the name:
You should try:
SELECT * FROM `test` ORDER BY SUBSTR(name,0,1), age;
What you encountered is absolutely expected behaviour. Why? If you sort first by name, you get results sorted for the full strings in the name column, where
'adam' < 'ali' < 'anton'
If there were more than one rows with name='adam', but different ages, like this:
ID NAME AGE
---------------------
1 adam 23
5 anton 18
8 ali 13
9 adam 52
You would get this result for SELECT * FROM test ORDER BY name, age;
ID NAME AGE
---------------------
1 adam 23
9 adam 52
8 ali 13
5 anton 18
As it is first sorted by name column, where the two adam values are the same, and then sorts based on the age, where 23 is smaller than 52...
But now, sorting on first character of name, and age SELECT * FROM test ORDER BY SUBSTR(name,0,1), age;:
ID NAME AGE
---------------------
8 ali 13
5 anton 18
1 adam 23
9 adam 52
If I unserstand you correctly, what you want to do is to sort just on the first letter of the name, then on the age. - What you have gotten from mysql is just what I would expect from your query and data set. If you choose several columns for sort, the secound kicks in only if you have equal values in the first one, eg if you had two Adams, one 18 and one 20 years old, the two would be sorted by age. and if you had Adam and Beth, both 18, Beth would come after Adam in the "sort by age,name"
Let's say I have two tables, people and families.
families has two fields - id and name. The name field contains the family surname.
people has three fields - id, family_id and name - The family_id is the id of the family that that person belongs to. The name field is that person's first name.
It's basically a one to many relationship with one family having many people.
I want to get a lists of name sets, ordered by the highest occurrence of the largest set of names across families.
That probably doesn't make much sense...
To explain what I want further, we can score each set of names. The 'score' is the array size * number of occurrences across families.
For example, let's say two names, 'John' and 'Jane' both existed in three families - That set's 'score' would be 2*3 = 6.
How could I get an array of sets of names, and the set's 'score', ordered by each set's score?
Sample Result Set (I've put it in a table layout, but this could be a multi-dimensional array in PHP) - Note this is just randomly thought up and doesn't reflect any statistical name data.
names | occurrences | score
Ben, Lucy | 4 | 8
Jane, John | 3 | 6
James, Rosie, Jack | 2 | 6
Charlie, Jane | 2 | 4
Just to clarify, I'm not interested in sets where:
The number of occurrences is 1 (obviously, just one family).
The set size is 1 (just a common name).
I hope I have explained my somewhat complex problem - if anyone needs clarification please say.
OK, got it:
<?php
require_once('query.lib.php');
$db=new database(DB_TYPE,DB_HOST,DB_USER,DB_PASS,DB_MISC);
$qry=new query('set names utf8',$db);
//Base query, this filters out names that are in just one family
$sql='select name, cast(group_concat(family order by family) as char) as famlist, count(*) as num from people group by name having num>0 order by num desc';
$qry=new query($sql,$db);
//$qry->result is something like
/*
Array
(
[name] => Array
(
[0] => cathy
[1] => george
[2] => jack
[3] => john
[4] => jane
[5] => winston
[6] => peter
)
[famlist] => Array
(
[0] => 2,4,5,6,8
[1] => 2,3,4,5,8
[2] => 1,3,5,7,8
[3] => 1,2,3,6,7
[4] => 2,4,7,8
[5] => 1,2,6,8
[6] => 1,3,6
)
[num] => Array
(
[0] => 5
[1] => 5
[2] => 5
[3] => 5
[4] => 4
[5] => 4
[6] => 3
)
)
$qry->rows=7
*/
//Initialize
$names=$qry->result['name'];
$rows=$qry->rows;
$lists=array();
for ($i=0;$i<$rows;$i++) $lists[$i]=explode(',',$qry->result['famlist'][$i]);
//Walk the list and populate pairs - this filters out pairs, that are specific to only one family
$tuples=array();
for ($i=0;$i<$rows;$i++) {
for ($j=$i+1;$j<$rows;$j++) {
$isec=array_intersect($lists[$i],$lists[$j]);
if (sizeof($isec)>1) {
//Every tuple consists of the name-list, the family list, the length and the latest used name
$tuples[]=array($names[$i].'/'.$names[$j],$isec,2,$j);
}
}
}
//Now walk the tuples again rolling forward, until there is nothing left to do
//We do not use a for loop just for style
$i=0;
while ($i<sizeof($tuples)) {
$tuple=$tuples[$i];
//Try to combine this tuple with all later names
for ($j=$tuple[3]+1;$j<$rows;$j++) {
$isec=array_intersect($tuple[1],$lists[$j]);
if (sizeof($isec)>0) $tuples[]=array($tuple[0].'/'.$names[$j],$isec,$tuple[2]+1,$j);
}
$i++;
}
//We have all the tuples, now we just need to extract the info and prepare to sort - some dirty trick here!
$final=array();
while (sizeof($tuples)>0) {
$tuple=array_pop($tuples);
//name list is in $tuple[0]
$list=$tuple[0];
//count is sizeof($tuple[1])
$count=sizeof($tuple[1]);
//length is in $tuple[2]
$final[]=$tuple[2]*$count."\t$count\t$list";
}
//Sorting and output is all that is left
rsort($final);
print_r($final);
?>
I am sorry I just realized I use a query lib that I can't source in here, but from the comment you will easily be able to create the arrays as in the section "Initialize".
Basically what I do is starting with the pairs I keep an array of the families all the names in the current name list belong to, then intersect it with all not-yet tried names.
Will this work?
SELECT
f.name AS 'surname',
GROUP_CONCAT(DISTINCT p.name ORDER BY p.name) AS 'names',
COUNT(DISTINCT p.name) AS 'distinct_names',
COUNT(p.id) AS 'occurrences',
COUNT(DISTINCT p.name) * COUNT(p.id) AS 'score'
FROM
families f
LEFT JOIN people p ON ( f.id = p.family_id )
GROUP BY
f.id
ORDER BY
f.name