How to Join same table in laravel - laravel

I wan to wirte a join query to connect same table, and without ON, but when i write it in laravel without on it is showing error
$key = DB::table('api_keys as ak')
->join('api_keys as bk','')
->where('ak.api_key', $api_key)->where('ak.user_id',0)
->pluck('api_key');
want to build the below query,
SELECT * FROM `api_keys` as ak
JOIN `api_keys` as bk
WHERE ak.`api_key`=$akey
and ak.`user_id`=$auser
and bk.`user_id`=$bsuer
and bk.`api_key`=$bkey

You must provide an ON clause for the join. More about where ON clauses are required can be found in this answer.
You can view the generated query using toSql() on a QueryBuilder object:
echo $key = DB::table('api_keys as ak')
->join('api_keys as bk','')
->where('ak.api_key', $api_key)->where('ak.user_id',0)
->toSql();
Which in your case returns:
select * from `api_keys` as `ak` inner join `api_keys` as `bk`
on `` `` where `ak`.`api_key` = ? and `ak`.`user_id` = ?
In your case it isn't totally clear what you are trying to achieve, but you might consider joining on api_key or the primary key of the api_keys table, if that is different:
$key = DB::table('api_keys as ak')
->join('api_keys as bk','ak.api_key', '=', bk.api_key)
->where('ak.api_key', $api_key)->where('ak.user_id',0)
->pluck('api_key');

DB::table('registerusers as a')
->join('registerusers as b', 'a.id', 'b.refer_id')
->where('a.username', 'b.username')
->where('b.id', 'a.refer_id')
->value('b.id');

without using on clause in laravel query builder you can use following
$key = DB::table(DB::raw('api_keys as ak, api_keys as bk'))
->where('ak.api_key', '=', $api_key)
->where('ak.user_id','=',0)
->where('ak.PK','=','bk.PK')
->pluck('ak.api_key')
where PK references to your table's primary key.
result will in your case.
select * from api_keys as ak, api_keys as bk where ak.api_key= 'api_key_value' and ak.user_id = 0 and ak.PK = bk.PK

I solved this by creating my own class and starting out with a base query which I modify to apply the join (using Laravel's joinSub function) as follows:
public function __construct()
{
$this->query = DB::table('question_responses as BASE');
}
public function applyFilter($questionId, $questionValue) {
$filterTableStr = 'filter_table_'.$questionId;
$filterIdStr = 'filter_id_'.$questionId;
$filterQuery = DB::table('question_responses AS '.$filterTableStr)
->select('survey_response_id AS '.$filterIdStr)
->where($filterTableStr.'.question_short_name', $questionId)
->where($filterTableStr.'.value', $questionValue);
$resultTableStr = 'result_table_'.$questionId;
$this->query = $this->query
->joinSub($filterQuery, $resultTableStr, function($join) use ($resultTableStr, $filterIdStr) {
$join->on('BASE.survey_response_id', '=', $resultTableStr.'.'.$filterIdStr);
});
}
After applying my required filters I can just call $this->query->get() as normal to obtain the result.
The important part was to make sure that each resulting table and join fields has unique names.
With this method I can apply unlimited filters to my base query.

Related

Laravel 8 - How I do where clause in table added with join

Hi I want to know how can i do this query in Laravel 8 , I tried adding the join clause but not work as expected, i need join clause? Or maybe there is another form to do it. I search others examples but i donĀ“t see anythat help me. The query is the next:
DB::table('escandallo_p as esc')
->select("esc.material", "esc.referencia", "esc.ancho", "esc.proveedor", "esc.punto",
"esc.precio", "esc.consumo", "esc.veces", "esc.001", "esc.002", "esc.003", "esc.004",
"esc.005", "esc.006", "esc.007", "esc.008", "esc.009", "esc.010", "esc.011", "esc.um", "esc.merma", "esc.importe", "esc.tipo", "esc.xtalla", "esc.fase",
DB::raw("(select anulado from prototipos_p as p where p.prototipo = '".$scandal[0]->prototipo."' and p.tipo = 'c' and p.referencia = esc.referencia )"),
// ignore
//original query "(select anulado from prototipos_p as p where p.prototipo = ",$request->prototipo," and p.tipo = 'c' and p.referencia = esc.referencia ) as 'anulado'",
// "(select clase from prototipos_p as p where p.prototipo = ",$request->prototipo," and p.tipo = 'c' and p.referencia = esc.referencia ) as 'clase'")
//Converted query ->select('pro.anulado')->where('pro.prototipo', $request->prototipo)
// ->where("p.prototipo", "=", $request->prototipo)
->where("esc.id_escandallo", "=", $request->id_escandallo)
->where("esc.id_version", "=", $request->version)
->orderBy("id","asc")
->get();
!!!! I need to pass the esc.referencia to the sub select query
The second select is the conversion of the select inside "" ( i know this is wrong is only for explain it).
Thank you in advance for any suggestion.
Best regards
EDIT: I can solve my problem with DB::raw, but if anyone know others methos are welcome!
You need to pass callback to the join query to add the extra query to the laravel's join method,
Example from Laravel Doc:
DB::table('users')
->join('contacts', function ($join) {
$join->on('users.id', '=', 'contacts.user_id')
->where('contacts.user_id', '>', 5);
})
->get();
It is explained in Laravel's doc, Advanced Join Clauses
There is Subquery support too Subquery Joins,
Eg:
$latestPosts = DB::table('posts')
->select('user_id', DB::raw('MAX(created_at) as last_post_created_at'))
->where('is_published', true)
->groupBy('user_id');
$users = DB::table('users')
->joinSub($latestPosts, 'latest_posts', function ($join) {
$join->on('users.id', '=', 'latest_posts.user_id');
})
->get();
These two might help you to achieve what you are trying
After test joins, joinSub, whereIn and other forms of doing this, I solved my problem using the DB::raw():
DB::table('escandallo_p as esc')
->select('parameters',....,
DB::raw("(SELECT column //(ONLY ONE)
FROM table
WHERE column = '".$parameter."' ...) AS nombre"),
)
->where('column', "=", $parameter)
->orderBy("id","asc")
->get();

Doctrine Many-To-Many bulk insert

I need to do a bulk insert of thousands of records (5k up to 20k).
The scenario is User<->n:m<->Group. The list of users is obtained by a complex query with many joins.
I have access to the QueryBuilder that generates the list.
The simpliest approach to add the users to the group is
$users = $this->repository->findRecipientsByCriteria($group->getCriteria());
foreach ($users as $user){
$group->addUser($user);
}
But for the number of users involved i don't think it's a good idea (in term of performances).
I can't even iterate results because of the fetch join relations.
I would like to inject the QueryBuilder Dql (or Sql) to the INSERT statement?
I mean something like:
$qb = $this->repository->getRecipientsByCriteriaQueryBuilder($group->getCriteria());
$qb->select("'".$group->getId()."' AS gruppo_id, U.id AS utente_id");
$d = $qb->getQuery()->getSQL();
$q = $this->entityManager->createNativeQuery('INSERT INTO `msg_gruppo_utente` (`gruppo_id`, `utente_id`) '.$d, new ResultSetMapping());
$q->execute();
But this results in
INSERT INTO `msg_gruppo_utente` (`gruppo_id`, `utente_id`) SELECT '64f105a3-a6ab-460a-8378-84b0c3258601' AS sclr_0, s0_.id AS id_1 FROM security_utente s0_ INNER JOIN security_utente_cliente s1_ ON s0_.id = s1_.utente_id INNER JOIN api_cliente a2_ ON s1_.cliente_id = a2_.id INNER JOIN api_indirizzo_cliente a3_ ON a2_.id = a3_.cliente_id INNER JOIN api_contratto a4_ ON a2_.id = a4_.cliente_id WHERE s1_.verificato = ? AND a3_.city = ?
Where parameters are not set, while i thought thatthe parameters should have been be set in getRecipientsByCriteriaQueryBuilder
Due to doctrine native SQL resctrictions
If you want to execute DELETE, UPDATE or INSERT statements the Native
SQL API cannot be used and will probably throw errors. Use
EntityManager#getConnection() to access the native database connection
and call the executeUpdate() method for these queries.
I've used this solution (executeUpdate is deprecated in favor of executeStatement)
$usersQueryBuilder = $this->repository->getRecipientsByCriteriaQueryBuilder($group->getCriteria());
$usersQueryBuilder->select("'".$group->getId()."' AS gruppo_id, U.id AS utente_id");
$parameters = $usersQueryBuilder->getParameters();
$p = [];
/** #var Parameter $parameter */
foreach ($parameters as $parameter){
$p[] = $parameter->getValue();
}
$conn = $this->entityManager->getConnection();
$conn->executeStatement('INSERT INTO `msg_gruppo_utente` (`gruppo_id`, `utente_id`) '.
$usersQueryBuilder->getQuery()->getSQL(), $p);

Laravel 5.6 Custom Query Build showing empty result

No errors, just an empty result. I am trying to work out why this query within a model is showing an empty collection.
Mysql Workbench query:
select
u.`name`, u.email, ual.admin, a.account_name
from
users as u
join users_account_link as ual on u.id = ual.user_id and u.account_id_in_use = ual.account_id
join accounts a on ual.account_id = a.id
where
u.sub = 'ABCDE';
Spits one row containing the desired result set.
Recreating this in Laravel query builder:
$settings = DB::table('users as u')
->join('users_account_link as ual', function ($join) {
$join->on('u.id', '=', 'ual.user_id')
->where('u.account_id_in_use', '=', 'ual.account_id');
})
->join('accounts as a', 'ual.account_id', '=', 'a.id')
->select('u.name as user_name', 'u.email as user_email', 'ual.admin as admin_check', 'a.account_name')
->where('u.sub',auth()->user()->sub)
->get();
dd($settings);
Provides an empty collection. I have done many custom queries which work well however the problem I have narrowed down the result set is the additional condition for join users_account_link as ual on u.id = ual.user_id and u.account_id_in_use = ual.account_id and have tried to move this condition to a where clause which still provides an empty result.
'u.account_id_in_use', '=', 'ual.account_id' are both integers however replacing u.account_id_in_use with a hardcoded integer e.g. 2 would return a result. Therefore, Laravel seems to have an issue with this field and replaced the where-> with a whereRaw now returns the desired result.
For anyone having a similar issue, try replacing fields with hardcode values to isolate the issue and look into using raw when possible to overcome the issue.
Hope this helps anyone in need.

How to make and condition with or in laravel query

My query is as below
SELECT * FROM `user_register`
INNER JOIN `locationdetail` on `locationdetail`.`userid` = `user_register`.`id`
INNER JOIN `lifestyle` on `lifestyle`.`userid` = `user_register`.`id`
WHERE `lifestyle`.`drink` in (2) and
( `locationdetail`.`state_id` in (4121) or `locationdetail`.`country_id` in (38))
In this query how to make bracket inner query in laravel model
Sorry there got distracted
$drinks = [1];
$state_ids = [1,2]
$country_ids = [1,2,3]
$someModel
->join() // enter your joins here
->whereIn('lifestyle.drink', $drinks)
->where(function( $q1 ) use ($state_ids, $country_ids) {
// insert the whereOr queries here against the $q1 using the data in `use` params
})
->get();
To check your query there is a toSql() function you can use in laravel too.

What is the equivalent query of laravel on this?

This is the native sql:
$sql = "Select count(name) from users Where email = 't#t.com' and user_id = 10";
I have this laravel code:
$checker = Customer::whereEmailAndUserId("t#t.com",10)->count("name");
Is this a correct way to do it in laravel?
You have to use where helper function and pass an array of checks. For example in your code it will be:
$checker = Customer::where([
['email', '=', 't#t.com'],
['user_id' '=', '10']
])->count();
Note: Please use the appropriate column name as it in table.
Assuming Customer model represents table users, you'll get query with eloquent like this:
Customer::where('email', 't#t.com')->where('user_id', 10)->select(\DB::raw('count(name)'))->get();
The option you are trying is incorrect
here is the right option
$users = \App\Customer::where('email','t#t.com')
->where('user_id',10)
->count()
Explanation of above code
App\Customer is the Model class and I am trying to read records where email = 't#t.com you can use various comparison operators like <,> and so on and you can also use the same function to for string pattern matching also
Eg.
$users = \App\Customer::where('email','%t.com')
->where('user_id',10)
->count()
You can use the same where function for Null Value test also
Eg.
$users = \App\Customer::where('email','=', null)
->where('user_id',10)
->count()
The above where clause will be converted to is null test of the SQL
You can read more here

Resources