how to join two tables using eloquent or query builder - php

I have this query which basically lists topics that two users have in common.
$subcommon= SubjectUser::selectRaw('topic_id, count(topic_id) AS aggregate')
->whereIn('user_id', [4, 2])->groupBy('topic_id')
->having('aggregate','>',1)->get();
For example the query result for the table below would be
{"topic_id":3,"aggregate":1}
tableone
id|user_id|topic_id
1|2 |3
2|4 |3
3|5 |1
I have another table(tabletwo) that also has topic_id which I would like to join so that I get the query result of row 2 from the second table. How would I go about doing this?
tabletwo
id|group_id|topic_id
1|6 |2
2|7 |3
3|7 |1

DB::table('tableone')->join('tabletwo', function($join) {
$join->on(tableone.topic_id, '=', tabletwo.topic_id);
})->get();

try this,
$subcommon= DB::table('tableone')
->selectRaw('topic_id, count(topic_id) AS aggregate')
->join('tabletwo','tabletwo.topic_id', '=', 'tableone.topic_id')
->whereIn('user_id', [4, 2])
->groupBy('tableone.topic_id')
->having('aggregate','>',1)
->get();

Related

Any idea how to Convert this to Laravel Query Builder

DB::select("select encoded_datas.* from encoded_datas inner join
(select data_user_firstname, data_user_lastname, data_user_barangay from encoded_datas t
group by data_user_firstname, data_user_lastname, data_user_barangay
having count(*)>1) t1
on encoded_datas.data_user_firstname=t1.data_user_firstname and encoded_datas.data_user_lastname=t1.data_user_lastname and encoded_datas.data_user_barangay=t1.data_user_barangay");
It's a working piece of query code, but it is so slow to load compare to Eloquent/Proper Query Builder.
Can anyone here help me convert this to Laravel's Query Builder format..
try this solution
DB::connection(your_connection)
->table('encoded_datas')
->select('encoded_datas.*')
->join(
DB::raw("SELECT data_user_firstname, data_user_lastname, data_user_barangay FROM encoded_datas t GROUP BY data_user_firstname, data_user_lastname, data_user_barangay HAVING COUNT(*) > 1) t1"),
function($join {
$join->on('encoded_datas.data_user_firstname', '=', 't1.data_user_firstname')
->on('encoded_datas.data_user_lastname', '=', 't1.data_user_lastname')
->on('encoded_datas.data_user_barangay', '=', 't1.data_user_barangay');
})
)
but I don't think it will speed up execution
Sometimes sending multiple requests might be less expensive then sending one nested.
You can try getting the ids of the duplicate rows first
$ids = DB::table('datas')
->select('firstname','lastname', DB::raw('COUNT(*) as `count`'))
->groupBy('firstname', 'lastname')
->havingRaw('COUNT(*) > 1')
->pluck('id');
Then get datas
$datas = Datas::whereIn('id', $ids)->get();
In your example you are executing two queries and a join.
Here we are executing 2 queries only, 1 of which uses primary key index, which should be instant. Technically its should be faster, looks cleaner as well
I've tried Alexandr's code:
$ids = DB::table('datas')
->select('firstname','lastname', DB::raw('COUNT(*) as `count`'))
->groupBy('firstname', 'lastname')
->havingRaw('COUNT(*) > 1')
->pluck('id');
$datas = Datas::whereIn('id', $ids)->get();
But it only shows single data/record.. What i want to get is something like this:
**id** |firstname |lastname
1 | John | Legend
2 | john | Legend
3 | Michael | Mooray
4 | Smith | West
5 | smith | West
so Im expecting to get the following result:
john |Legend
john |Legend
Smith |West
Smith |West

Count does not work as expected in Laravel Query Builder

I am trying to get how many names do I have in database. For this purpose I am using Query Builder like this:
$namesIdsCount = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having)
->count();
Is says that 24, which is not correct, because if I will write code like this:
$namesIdsCount = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having)
->get();
result object contains 247 elements, which is correct. I have tried to play with skip/take, but still no results. Where am I wrong? Thanks for any help.
I think it's the other way around, you're not getting 24 groups. You're getting 24 elements within the first group. That configuration results in the following query:
SELECT
COUNT(*) AS 'aggregate',
`name_id`
FROM `names_to_options`
WHERE EXISTS(
{your $havingRaw sub-query}
)
GROUP BY `name_id`;
What you end up with will look something like this:
+---------------+---------+
| aggregate | name_id |
+---------------+---------+
| 24 | 1 |
+---------------+---------+
| 5 | 2 |
+---------------+---------+
| 30 | 3 |
+---------------+---------+
| ... and so on | 4 |
+---------------+---------+
Query\Builder just doesn't realize you can get more than one result back when count() is involved.
You were pretty close to the right answer yourself though.
$namesIdsCount = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having)
->get();
get() returns an Eloquent\Collection, child of Support\Collection, which has its own version of the count method. So your answer is just:
$namesIdsCount = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having)
->get()
->count();
If you really want this to happen in MySQL, the query you want to happen would look like this:
SELECT COUNT(*) FROM (
SELECT
`name_id`
FROM `names_to_options`
WHERE EXISTS(
{your $havingRaw sub-query}
)
GROUP BY `name_id`
) AS temp;
For that, you can do this:
$query = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having);
$sql = $query->toSql();
$values = $query->getBindings();
$count = DB::table(DB::raw('('.$sql.') AS `temp`'))
->selectRaw("COUNT(*) AS 'aggregate'", $values)
->first()
->aggregate;
MySQL performance can get a little hairy when asking it to write temp-tables like that though, so you'll have to experiment to see which option is faster.
Inuyaki is right
(id, name_id),
(1,1),
(2,1),
(3,2),
(4,3)
There are are four rows so get() method will return 4 rows
but there are three groups if you use groupBy [name_id]
1 (1,1)
2 (2)
3 (3)
now count will return 3
hope this will help.

How to extract all rows which is duplicates in laravel?

I want to get all rows which is the same name and location from Users Table
**id** |name |location |phone_number
1 |John | Europe |0988884434
2 |john | Europe |0933333333
3 |Michael |Europe |0888888888
4 |Smith |Dubai |082388888888
5 |Smith |Dubai | 03939494944
I want to get all rows which is the same name and location like
john |Europe
john |Europe
Smith |Dubai
Smith |Dubai
here is how i tried to do
$duplicates = DB::table('users')
->select('name','location', DB::raw('COUNT(*) as `count`'))
->groupBy('name', 'location')
->having('count', '>', 1)
->get();
but this is just showing only one row which is duplicates like
john |Europe
Smith|Dubai
Any help or advice you have would be greatly appreciated.
Use havingRaw:
$duplicates = DB::table('users')
->select('name','location', DB::raw('COUNT(*) as `count`'))
->groupBy('name', 'location')
->havingRaw('COUNT(*) > 1')
->get();
I also wasn't sure of the syntax, but the Laravel documentation seems to imply that the alias you defined in the select clause is not available in the normal having() function.
To get All Rows rather than a total count of a group of duplicate rows would look like the following;
$duplicates = DB::table('users')
->select('id', 'name', 'location')
->whereIn('id', function ($q){
$q->select('id')
->from('users')
->groupBy('name', 'location')
->havingRaw('COUNT(*) > 1');
})->get();

Laravel. Eloquent query for two tables

I want to write laravel eloquent query which could select all the titles from titles table where title_id doesnt't exist in title_count table. Here is an example. titles table:
title_id
1
2
3
4
title_count table:
title_id
3
4
So my query should select titles with id's 1, 2 from title table. To be honest, I have no ideo how to do it. I'm using laravel 5. I hope you can help me. Thanks in advance!
Use a join to to identify titles that do not appear in title_count.
DB::table('titles')->leftJoin('title_count', 'titles.title_id', '=', 'title_count.title_id')
->select('titles.*')
->whereNull('title_count.title_id')
->get();
Try this
DB::table('titles')->whereNotExists(function($query)
{
$query->select(DB::raw(1))
->from('title_count')
->whereRaw('title_count.title_id = titles.title_id');
})->get();
Not tested
DB::table('title_count')
->leftJoin('titles as t', 't.title_id', '=', 'title_count.title_id')
->select('t.*')
->where('t.title_id', '!=', 'title_count.title_id')
->get();

Laravel Eloquent ORM query

I have been trying this mysql query to convert into laravel query but I am unable to figure it out.
SELECT max(a.date) as max FROM table1 a, table2 b where
a.publishing_time<='2015-02-27 12:30:00' and a.Status='1' and
a.id=b.table1_id
table 1 fields are:-
sl | date | publishing_time | status
table 2 fields are
sl | table1_id | additional_fields
I am stucked on this please help me
Try this Laravel query
DB::table('table1 as a')
->select(DB::raw('max(a.date) as max_date'))
->join('table 2 as b', 'a.id', '=', 'b.table1_id')
->where('a.publishing_time'<='2015-02-27 12:30:00')
->where(Status='1')
->get();
Try this..
This is laravel join query
$resource = DB::table('table1')->join('table2', 'table1.id', '=', 'table2.table1_id')->where('table1.publishing_time','<=','2015-02-27 12:30:00')->where('table1.Status','1');
Try something like:
DB::table('table a as a')->join('table b as b', 'a.id', '=', 'b.table1_id')->max('a.data as max')->where('a.publishing_time', '<=', '2015-02-27 12:30:00')->where('a.status', 1)->get();

Categories