Grouping two arrays by their values ​with Laravel - php

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.

Related

trouble returning both partial and exact matches

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.

Unique value count of comma separated field (PHP - MySQL)

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

MySQL Count in PHP while loop only returns one result then Null

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);

MySQL select unique values based on one or more possible clauses

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)';

mysql order by issue

if i have a query like :
SELECT * FROM table WHERE id IN (3,6,1,8,9);
this array of the ids is build in php dynamically ,
and the order is important to me.
$my_array = array (3,6,1,8,9) ;
how can i sort the results by the order by which the elements appear in my array ?
its possible to do it in MYSQL query,
or i must to order it after via php ?
You can order by a value derived from a column. You can use a CASE operator to specify the order:
SELECT * FROM table
WHERE id IN (3,6,1,8,9)
ORDER BY CASE id WHEN 3 THEN 1
WHEN 6 THEN 2
WHEN 1 THEN 3
WHEN 8 THEN 4
WHEN 9 THEN 5
END
I haven't tested but this PHP solution should work:
<?php
$my_array = array (3,6,1,8,9) ;
$sql = 'SELECT * FROM table WHERE id IN (3,6,1,8,9)';
$sql .= "\nORDER BY CASE id\n";
foreach($my_array as $k => $v){
$sql .= 'WHEN ' . $v . ' THEN ' . $k . "\n";
}
$sql .= 'END ';
echo $sql;
?>
This generates the following SQL code:
SELECT * FROM table WHERE id IN (3,6,1,8,9)
ORDER BY CASE id
WHEN 3 THEN 0
WHEN 6 THEN 1
WHEN 1 THEN 2
WHEN 8 THEN 3
WHEN 9 THEN 4
END
If you must do it this way you'll have to manipulate the data in PHP. MySQL can only order by natural orderings ascending or descending.
Got to question though - why do you need the data returned in this very specific order? There may be an easier solution to your problem by re-jigging something further up in the code.
SELECT * FROM table WHERE id IN (3,6,1,8,9) ORDER BY FIELD(id,3,6,1,8,9);
You can load the results into an array with IDs as indexes:
while ($row = mysql_fetch_array($l)) $items[$row['id']] = $row;
and then simply iterate it in your order
foreach ($my_array as $id) { $current_row = $items[$id]; ... }

Categories