I have a table like this:
product_id attribute_id
2 7,8
1 2,7
3 7
I also have a variable called $search_ids which contains values to search for.
If $search_ids has a value of 7 , I want it to return all 3 rows, but if it has a value of 2,7 or 7,8 I then want to return that row only.
I tried the following where $search_ids has a value of 7, but this doesn't return the second row! And if I change the row's value from 2,7 to 7,2 then it returns that row also!
So right now the following query:
$q = "SELECT product_id FROM product_attributes
WHERE attribute_id IN ('$search_ids')
OR attribute_id IN ($search_ids)
returns
2
3
instead of
2
1
3
I would do it this way:
$search_ids = '2,7'; //dummy data
$q = '';
$ids = explode(',', $search_ids);
foreach ($ids as $id) {
$q .= (strlen($q) == 0)?'':' AND';
$q .= ' FIND_IN_SET(\''.$id.'\', attribute_id) > 0';
}
$q = 'SELECT product_id FROM product_attributes WHERE' . $q;
Try this:
$q = "SELECT product_id FROM product_attributes
WHERE attribute_id REGEXP '(^|,)($search_ids)(,|$)'";
This will match on rows where product_id matches $search_ids if it is exactly a match, at the start of a comma separated list, in the middle of a comma separated list, or at the end of a comma separated list.
Related
Two or 3 ids are coming in $pks as follows and I am sending these id values in sql. For example, when this for runs 3 times, total_ticket and from_user_id values will come in 3 different arrays. How can I group these 3 arrays according to from_user_id value? So I want to make it into a single array
so I want to group the 2 or 3 $props returned by the value from_user_id
$pks = $request->input('pkids');
for ($i = 0; $i < count($pks); $i++) {
$pk = PK::findOrFail($pks[$i]);
$table_ym = date('Ym', $pk->create_time);
$table = 'video_' . $table_ym;
$props = DB::select('select sum(total_ticket) as total_ticket, from_user_id from '
. $table . ' where pk_id=' . $pk->prop_pk_id . ' group by from_user_id');
}
Essentially this is all you have to do:
$pks = $request->input('pkids');
$pks = array_filter(array_map('intval', $pks)); //int's above 0 only
$results = DB::select('
SELECT
SUM(total_ticket) AS sum_total_ticket,
MIN(create_time) AS min_create_time,
from_user_id
FROM
'.$table.'
WHERE pk_id IN ('.implode(',', $pks).')
GROUP BY from_user_id');
This will return 1 row per from_user_id with the total_ticket as that "groups" sum. I also included the min create time which will be the lowest value of that group for that column. Or the first (earliest) created date.
All you have to do is retrive the results which should look like this
sum_total_ticket min_create_time from_user_id
53 2022-08-20 00:00:00 1
224 2021-08-20 00:00:00 18
Make sense.
I'm storing multiple numbers in a MySQL column by using a delimiter like this ("1,5,10"). I didn't know that it's not a good way to store the data, but now I have no choice left.
Anyway, I have a table Like this:
MovieID | genre
------------------------------------
1 1,2,3
2 2,4
3 1,2
4 2,5,10
I want to filter the movies by the genre ids. Such as, if I search for genre id 1,2, all the movies will be fetched which contain these genre ids.
I have tried:
AND FIND_IN_SET('".$genre_list."',genre) > 0
AND genre IN('".$genre_list."')
AND genre LIKE('%".$genre_list."%')
But nothing worked.
I'm doing like this:
function make_query($minimum_rating, $maximum_rating, $category, $country){
$query = "
SELECT * FROM videos
WHERE publication = '1'
";
if (isset($minimum_rating, $maximum_rating) && !empty($minimum_rating) && !empty($maximum_rating)) {
$query .= "
AND imdb_rating BETWEEN '".$minimum_rating."' AND '".$maximum_rating."'
";
}
if (isset($category)) {
// $category_filter = implode("','", $category);
foreach ($category as $cat){
$query .= "
AND FIND_IN_SET('$cat', genre) > 0
";
}
}
if (isset($country)) {
$country_filter = implode("','", $country);
$query .= "
AND country IN('".$country_filter."')
";
}
return $query;
}
It only shows the movies which contain the genres like if the array contains 1,2,3. It fetches the MovieID 1.
My expected outcome was MovieID 1,2,3,4
You can use RLIKE for every genre matching.
For example if You want to find rows with genres 1,5 You can run this:
select * from videos where genre RLIKE '^1$|^1,|,1$|,1,' AND genre RLIKE '^5$|^5,|,5$|,5,';
I have mysql table that looks like this:
id place interest
1 place1 a,b,c
2 place2 c,d,e
3 place1 a,e
4 place2 f
5 place2 f
6 place3 g,h
I need to get unique "place" and "interest" values sorted as per the count.
So, the output for "place" would be
place2(3)
place1(2)
place3(1)
So, the output for "interest" would be
a(2)
c(2)
e(2)
f(2)
b(1)
d(1)
g(1)
h(1)
is there a way to do this in PHP-Mysql?
So, far I have been able to get simple column data
SELECT place,
COUNT( * ) AS num
FROM testtab
GROUP BY place
ORDER BY COUNT( * ) DESC
As mysql is not able to hold arrays, its better to build a new table like this:
interest_id interest_name
1 a
2 b
and another one to keep the relations:
pk id interest_id
1 1 1
2 1 2
which this id is the id of the records in your main table.
With having this, you can easily use:
select count(*) from THIRD_TABLE where id = YOUR_ID
You can do this.
$place = array();
$interests = array();
foreach($rows as $row){
if (!isset($place[$row["place"]])){
$place[$row["place"]] = 0;
}
$place[$row["place"]]++;
$ints = explode(",", $row["interests"]);
foreach($ints as $int){
if (!isset($interests[$int])){
$interests[$int] = 0;
}
$interests[$int]++;
}
}
This will give you the two arrays keyed off of the relevant field with the value being the count. If this is going to be a common action in your application it would make more sense to normalize your data as suggested by AliBZ.
This is for the first result you need
SELECT place,COUNT(interest)
FROM `testtab`
GROUP by place
ORDER BY COUNT(interest) desc
can do this :
$inst_row = '';
foreach($rows as $row){
$inst_row .= $row['interests'];
}
$inst_values = explode(',', $inst_row);
$inst_count = array_count_values($inst_values);
// $inst_count will return you count as you want ,print_r it and format it accordingly
Ok, so I have some MySQL tables as follows:
Buildings
Building-ID Building-Name
===========----=============
1 Building-1
2 Building-2
3 Building-3
4 Building-4
Building-1
Mroom State
=====----======
1 Booked
2 Empty
3 Empty
4 Empty
Building-2
Mroom State
=====----======
1 Booked
2 Empty
3 Empty
4 Empty
And a query in PHP as follows (Ignore the hard coded while, I've simplified the code a bit):
$sql = "select * from Buildings";
$result = mysql_query ($sql) or die(mysql_error());
while ($row = mysql_fetch_array($result))
{
$building[] = $row['ward_name'];
}
$v1 = 0;
while ($v1 < 4)
{
$sql = "SELECT COUNT(*) FROM `$building[$v1]` WHERE state = 'Empty'";
$result = mysql_query($sql) or die(mysql_error());
$count = mysql_result($result, 00);
var_dump($count[$v1]);
$v1 = $v1 + 1;
}
To my way of thinking this should create an array of the buildings contained in the "Buildings" table, start a loop, load the building name from the array and provide a row count for the table of how many rows contain "Empty" in the state column. What it actually does is provide a count for the first table and then provides "NULL" for the rest.
I'd appreciate any help you can give me.
Cheers!
What about changing your data model?
Table buldings can be kept as is:
Buildings
Building-ID Building-Name
===========----=============
1 Building-1
2 Building-2
3 Building-3
4 Building-4
New table:
Rooms
Building-ID Mroom State
===========-=====-=====
1 1 1
1 2 0
2 1 0
State 0 = Empty, State 1 = Booked
Then use a join with group by:
select count(*) from buildings b inner join rooms r on r.bid = b.id where r.state = 0 group by b.id;
Then you will get a row for each building with the count of empty rooms. You won't need a table for each building.
This does noit make sense:
$count = mysql_result($result, 00);
var_dump($count[$v1]);
you mean to write:
$count[$v1] = mysql_result($result, 00);
var_dump($count[$v1]);
Also do not use several tables with names matching columns of other tables.
You can use one table with a primary key that spans two columns instead, for example create primary key on($buildingid,$roomid)
so that the table has columns $buildingid,$roomid, and $state.
mysql_result() returns a string, not an array.
Modify the code and check that now it works as expected.
var_dump($count);
So there is this database table:
and this array with selected options:
$options[1] = 1;
$options[2] = 5;
$options[3] = 3;
$options[4] = 2;
$options[5] = 1;
...
$options[x] = y;
Now, the aim is to fetch all item_ids, where if there is an option_id in its row from one of the options array's keys, the value must be the same as the value in the options array.
For example:
option 1 has selected value 1
option 2 has selected value 5
option 3 has selected value 4
option 4 has selected value 2
so we should select item_id 1 and other item_ids, where if option 1 -> option 1 = 1 AND if option 2 -> option 2 = 5 AND if option 3 -> option 3 = 4 AND ...
The item_ids will be used in IN() to select the items data from the items table.
The main point is that the user selects some options on a page, then the options are put into array, then I must find all items that comply with the selected options. In the table above we have the relation between the items and the options, and the option values per item which are predefined.
$where = array();
foreach($options as $key => $value) $where[] = 'option_id = ' . $key . ' AND option_value = ' . $value;
$sql = 'SELECT DISTINCT item_id
FROM table
WHERE (' . explode(') OR (', $where) . ')';
I might have completely misunderstood your question however.
I think this might do it for you. Haven't tested it at all and it'll probably blow up, but...
SELECT *
FROM items
WHERE (item_id in (
SELECT item_id
FROM optiontable
WHERE ((option_id = 1) and (option_value = 1)) or
((option_id = 2) and (option_value=5)) or
((option_id = 3) and (option_value=3)) or
((option_id = 4) and (option_value=2)) or
((option_id = 5) and (option_value=1))
GROUP BY CONCAT(option_id, ',', option_value)
HAVING COUNT(CONCAT(option_id, ',', option_value)) = 5
));
Basically, the inner query pulls out all the rows that match one of the member rows in your required options row. It does an artificial grouping/count on the paired option_id/option_value pairs and returns the item_ids of the rows where the number of opt_id/opt_val pairs add up to 5 rows.
You'd have to build such a query dynamically in the client, so that the number of 'where' clause entries matches the number in the having clause.
<?php
$options = array(
1 => 1,
2 => 5,
3 => 3,
4 => 2,
5 => 1
);
$cases = array();
foreach($options as $id => $value){
$cases[] = "WHEN $id THEN $value";
}
$query =
'SELECT item_id '.
'FROM your_table '.
'WHERE option_value = CASE option_id '.implode(' ', $cases).' '.
'GROUP BY item_id';
echo $query;
?>
Output (formatted by me):
SELECT item_id
FROM your_table
WHERE option_value = CASE option_id
WHEN 1 THEN 1
WHEN 2 THEN 5
WHEN 3 THEN 3
WHEN 4 THEN 2
WHEN 5 THEN 1
GROUP BY item_id
Test this query and let me know if it works the way you expect it to. :)
Update: Suggestion for your final query
$query =
'SELECT * FROM items '.
'WHERE id IN('.
'SELECT item_id '.
'FROM your_table '.
'WHERE option_value = CASE option_id '.implode(' ', $cases).' '.
'GROUP BY item_id)';