Laravel 5.6 How to take duplicated datas from column - mysql

And that i want to print each topic_id's count
show.blade.php
#foreach($questions as $question)
{{ $question->topic_id }}
#endforeach
ExamsController#index
$topics = Topic::all();
return view('exams.show', compact('topics','questions'));
Just want to take duplicated datas count and print.
| id | topic_id |
| ---|:--------:|
| 1 | 4 |
| 2 | 9 |
| 3 | 5 |
| 4 | 5 |
| 5 | 2 |
| 6 | 4 |
| 7 | 5 |
that i wanted result is count of each topic_id duplicates. its like
| id | topic_id |
| ---|:--------:|
| 1 | 4 |
| 6 | 4 |
2
| id | topic_id |
| ---|:--------:|
| 3 | 5 |
| 4 | 5 |
| 7 | 5 |
count = 3

You could make use of groupBy
$duplicates = Topic::selectRaw("count('id') as total, topic_id")
->groupBy('topic_id')
->get();
// pass the duplicates along with other variables to the view
return view('exams.show', compact('topics','questions', 'duplicates'));
and in your view you could do
#foreach ($duplicates as $duplicate)
{{ $duplicate->topic_id }} - {{ $duplicate->total }}
#endforeach

maybe you can use collection feature on laravel to group data by topic_id
$topic = Topic::all();
$topicArray = $topic->groupBy('topic_id')->toArray();
in your view you can simply use $topicArray to display your data & count its duplicate
#foreach ($topicArray as $key => $value)
#foreach ($value as $key2 => $value2)
| {{ $value2['id'] }} | {{ $value2['topic_id'] }} |<br>
#endforeach
count {{ count($value) }}<br><br>
#endforeach

I am not sure what duplicated datas you mean, but I believe you are looking for a distinct.
The distinct method allows you to force the query to return distinct
results
https://laravel.com/docs/5.6/queries#selects
$topics = Topic::distinct()->get();

Related

How to multiply and group using laravel eloquent with relation

I'd like to export data from my database but have problems with multiplying and sum using laravel eloquent with relation
So i have 2 tables there (budgets, items)
Budget's:
// Table
+----+---------------+-----------------+------+-----+--------------------+
| id | delivery_plan | item_code | curr | qty | price |
+----+---------------+-----------------+------+-----+--------------------+
| 1 | 2022-08 | 201.0001 | IDR | 1 | 2000.0000000000 |
| 2 | 2022-08 | 201.0001 | IDR | 3 | 2000.0000000000 |
| 3 | 2022-07 | 201.9999 | IDR | 2 | 2000.0000000000 |
+----+---------------+-----------------+------+-----+--------------------+
// Relation
public function item()
{
return $this->belongsTo(Item::class, 'item_code', 'item_code');
}
Items :
// Table
+----+----------------+-----------+
| id | subgroup | item_code |
+----+----------------+-----------+
| 1 | KOMPONEN MESIN | 201.0001 |
| 2 | EQUIPMENT LAIN | 201.9999 |
+----+----------------+-----------+
// Relation
public function budgets()
{
return $this->hasMany(Budget::class, 'item_code', 'item_code');
}
So, the scenario is :
Multiply the "qty" * "price" columns and name them as "total" like so
Group them by "subgroup" column, which came from item() relationship
Group them by "delivery_plan"
I prefer using eloquent because to minimize the complexity because i need that "whereHas" method
This is what i've tried so far and isn't working :
$budgets = Budget::with('item', 'rate')->whereHas('period.term', function (Builder $builder) {
$builder->where('name', '=', Session::get('term-budget'));
})->where('section', Session::get('section-budget'))->getQuery();
$result = $budgets->sum('price * qty')->get();
How can i achieve this ?
This can be solved by a join with SUM(), something like below (untested):
Budget::leftJoin('items', 'budgets.item_code', '=', 'items.item_code')
->addSelect('subgroup')
->addSelect('delivery_plan')
->addselect(\DB::raw('SUM(qty * price) as total'))
->groupBy('subgroup', 'delivery_plan')
->get();

Laravel sub-query

I have a database that looks like this:πŸ‘‡πŸ‘‡
images πŸŒ…
| id | name | src | status |
| ------------- |---------------| ------------| ----------|
| 1 | nice sun set | 1020288.jpg | published |
| 2 | poor sun set | 1120288.jpg | published |
| 3 | best sun set | 3120288.jpg | deleted |
| ------------- |---------------| ------------| --------- |
image_views πŸ‘€
| id | image_id | browser_id🌎 | created_at |
| ------------- |---------------| ------------ | ------------------ |
| 1 | 2 | 1020288e3221 |2020-02-23 13:55:11 |
| 2 | 1 | 1120288221ww |2020-02-27 13:50:51 |
| ------------- |---------------| ------------ | ------------------ |
Now in my laravel App,
I want to get the most viewed image in the PAST last 7 days.
( i want to have a column of image_views and those views πŸ‘€ should be grouped by browser id ).
so here is what i have tried:πŸ‘‡πŸ‘‡
$image_views = DB::table('image_views')
->selectRaw('count(*) as view_count')
->where(function($query){
$query->where('image_views.image_id', 'images.id');
$query->whereDate('image_views.created_at', '>=', Carbon::now()->subDays(7)->toDateTimeString() );
});
$image = Image::select(['images.*', DB::raw('(' . $image_views->toSql() . ') as views ')])
->limit(1)
->orderBy('views', 'desc')
->where('images.status','published')
->mergeBindings($image_views)
->get();
return $image;
So unfortunately the posted above☝☝ code does not work😩
It only return blank results.
By the way i have lot of views in image_views table starting from 2⃣0⃣1⃣9⃣ to now, just that i couldn't post all here..
THE FUNNY THING IS THAT IF I CONVERT IT TO SQL AND PASTE IT IN PHPMYADMIN IT WORKS LIKE A CHARM
return $image->toSql();
//->mergeBindings($image_views)
//->get();
PLEASE SOMEONE TELL ME WHAT I AM DOING WRONG IN LARAVEL!!πŸ™Œ
Given images & image_views tables
$mostViewdImage = DB::table('image_views')
->join('images', 'image_views.image_id', '=', 'images.id')
->select('browser_id', DB::raw('count(image_id) as occurrence'), 'images.*')
->where('image_views.created_at', '>=', Carbon::now()->subDays(7)->toDateTimeString())
->groupBy('image_id', 'browser_id')
->orderByRaw('occurrence DESC')->first();
dump($mostViewdImage);
//Output
"select `browser_id`, count(image_id) as occurrence, `images`.* from `image_views` inner join `images` on `image_views`.`image_id` = `images`.`id` where `image_views`.`created_at` >= ? group by `image_id`, `browser_id` order by occurrence DESC limit 1" (2.02 s)
{#261 β–Ό
+"browser_id": "1020288e3221"
+"occurrence": 2
+"id": 2
+"name": "poor sun set"
+"src": "1120288.jpg"
+"status": "published"
}

How do I select records in MySQL with multiple columns matching map of values?

I have the following 3-column table:
+----+---------+------------+
| ID | First | Last |
+----+---------+------------+
| 1 | Maurice | Richard |
| 2 | Yvan | Cournoyer |
| 3 | Carey | Price |
| 4 | Guy | Lafleur |
| 5 | Steve | Shutt |
+----+---------+------------+
If I want to look for everyone in (Maurice,Guy) I can do select * from table where first in (Maurice,Guy).
If I want to find just Maurice Richard, I can do select * from table where first = "Maurice" and last = "Richard".
How do I do a map, an array of multiples?
[
[Maurice, Richard]
[Guy,Lafleur]
[Yvan,Cournoyer]
]
If I have an arbitrary number of entries, I cannot construct a long complex where (first = "Maurice" and last = "Richard") or (first = "Guy" and last = "Lafleur") or .....
How do I do the moral equivalent of where (first, last) in ((Guy,Lafleur),(Maurice,Richard)) ?
You can do it just like you describe it:
SELECT *
FROM mytable
WHERE (first, last) IN (('Guy','Lafleur'),('Maurice','Richard'))
Demo here

Count and select all dates for a specific field in MySQL

i have a data format like this:
+----+--------+---------------------+
| ID | utente | data |
+----+--------+---------------------+
| 1 | Man1 | 2014-02-10 12:12:00 |
+----+--------+---------------------+
| 2 | Women1 | 2015-02-10 12:12:00 |
+----+--------+---------------------+
| 3 | Man2 | 2016-02-10 12:12:00 |
+----+--------+---------------------+
| 4 | Women1 | 2014-03-10 12:12:00 |
+----+--------+---------------------+
| 5 | Man1 | 2014-04-10 12:12:00 |
+----+--------+---------------------+
| 6 | Women1 | 2014-02-10 12:12:00 |
+----+--------+---------------------+
I want to make a report that organise the ouptout in way like this:
+---------+--------+-------+---------------------+---------------------+---------------------+
| IDs | utente | count | data1 | data2 | data3 |
+---------+--------+-------+---------------------+---------------------+---------------------+
| 1, 5 | Man1 | 2 | 2014-02-10 12:12:00 | 2014-04-10 12:12:00 | |
+---------+--------+-------+---------------------+---------------------+---------------------+
| 2, 4, 6 | Women1 | 3 | 2015-02-10 12:12:00 | 2014-03-10 12:12:00 | 2014-05-10 12:12:00 |
+---------+--------+-------+---------------------+---------------------+---------------------+
All the row thath include the same user (utente) more than one time will be included in one row with all the dates and the count of records.
Thanks
While it's certainly possible to write a query that returns the data in the format you want, I would suggest you to use a GROUP BY query and two GROUP_CONCAT aggregate functions:
SELECT
GROUP_CONCAT(ID) as IDs,
utente,
COUNT(*) as cnt,
GROUP_CONCAT(data ORDER BY data) AS Dates
FROM
tablename
GROUP BY
utente
then at the application level you can split your Dates field to multiple columns.
Looks like a fairly standard "Breaking" report, complicated only by the fact that your dates extend horizontally instead of down...
SELECT * FROM t ORDER BY utente, data
$lastutente = $lastdata = '';
echo "<table>\n";
while ($row = fetch()) {
if ($lastutente != $row['utente']) {
if ($lastutente != '') {
/****
* THIS SECTION REF'D BELOW
***/
echo "<td>$cnt</td>\n";
foreach ($datelst[] as $d)
echo "<td>$row[data]</td>\n";
for ($i = count($datelst); $i < $NumberOfDateCells; $i++)
echo "<td> </td>\n";
echo "</tr>\n";
/****
* END OF SECTION REF'D BELOW
***/
}
echo "<tr><td>$row[utente]</td>\n"; // start a new row - you probably want to print other stuff too
$datelst = array();
$cnt = 0;
}
if ($lastdata != $row['data']) {
datelst[] = $row['data'];
}
$cnt += $row['cnt']; // or $cnt++ if it's one per row
}
print the end of the last row - see SECTION REF'D ABOVE
echo "</table>\n";
You could add a GROUP BY utente, data to your query above to put a little more load on mysql and a little less on your code - then you should have SUM(cnt) as cnt or COUNT(*) as cnt.

mysql group rows in joined query

Im stumbling upon a problem where i need to retrieve data from the following tables
events
+-------+---------+---------+
| e_id | e_title | e_link |
+-------+---------+---------+
| 1 | Event 1 | event_1 |
| 2 | Event 2 | event_2 |
| 3 | Event 3 | event_3 |
| 4 | Event 4 | event_4 |
| 5 | Event 5 | event_5 |
+-------+---------+---------+
reservations
+-------+---------+---------+
| r_id | r_e_id | r_u_id |
+-------+---------+---------+
| 1 | 2 | 1 |
| 2 | 2 | 3 |
| 3 | 5 | 4 |
| 4 | 2 | 4 |
| 5 | 1 | 1 |
+-------+---------+---------+
users
+-------+---------+----------+
| u_id | u_name | u_gender |
+-------+---------+----------+
| 1 | One | Male |
| 2 | Two | Male |
| 3 | Three | Female |
| 4 | Four | Male |
| 5 | Five | Female |
+-------+---------+----------+
I want to display an event page with the users that are subscribed to that event, like follows:
Event 2
Users:
- One
- Three
- Four
I have the following query with the problem that this one only displays the first user (so in this case Four), which makes sense because the mysql_fetch_assoc() is not in a while() loop.
$result = mysql_query("
SELECT events.e_title, reservations.*, users.u_name
FROM events
JOIN reservations
ON events.e_id = reservations.r_e_id
JOIN users
ON reservations.r_u_id = users.u_id
WHERE events.e_link = '".mysql_real_escape_string($_GET['link'])."'
");
$show = mysql_fetch_assoc($result);
What should i change in my query to make it work the way i want?
EDIT:
The solution from Teez works perfect, but wat if i want to attach more info, say for a link? My desired output is something like this:
Event 2
Users:
- User 1 Male
- User 3 Female
- User 4 Male
How am i going to achieve that? And eventually i even want to split the users by gender. So one list for females and one for males
SECOND EDIT:
I'm stunned with the result so far, but to complete it i want to sort the users by gender, like so:
Event 2
Users male:
- User 1 Male
- User 4 Male
Users female:
- User 3 Female
but how?
Best way will be first make a 2D array containing all events with respective users
Like below:
while( $show = mysql_fetch_assoc($result))
{
$events[$show['e_id']][]=$show['u_name'];
$uid[$show['e_id']][]=$show['u_id'];
}
Then loop arround above array for displaying :
foreach($events ad $key=>$users)
{
echo "Event ".$key."<br>";
echo "Users : <br>";
foreach($users as $ukey=>$name)
{
echo " -<a href='domain.com/user/".$uid[$key][$ukey]."'>".$name."</a>;
}
}
So with each call of mysql_fetch_assoc you want to have the event details and a list of usernames? In MySQL you can use GROUP_CONCAT for this purpose, although it is quite limited and error-prone. You should rather put mysql_fetch_assoc() in a loop to build an array of users. Anyway, here is the GROUP_CONCAT solution:
$result = mysql_query("
SELECT events.e_title, GROUP_CONCAT(users.u_name) e_reservation_users
FROM events
JOIN reservations ON events.e_id = reservations.r_e_id
JOIN users ON reservations.r_u_id = users.u_id
WHERE events.e_link = '".mysql_real_escape_string($_GET['link'])."'
GROUP BY 1
");
$show = mysql_fetch_assoc($result);
$show will then be
array('e_title' => '...', 'e_reservation_users' => '...,...,...').