How to apply condition to Laravel eloquent relation - database

I have a ProcessHistory and Person model I need a eloquent code for relation with multiple condition.
Conditions:
1. oindex = oindex
2. pat_id = pat_id
I want a eloquent code to get result of the following sql code
select * from tbl_process_history as s join tbl_persons as p on (s.oindex = p.oindex and s.pat_id = p.pat_id)
I need to get all the persons having same oindex and pat_id. I have tried with below eloquent code where I can apply condition inside of relation 'own'. Here I can apply only for as static value.
ProcessHistory::with(['own'=>function($query){
return $query->where('pat_id','');
}])->get();
I need a condition inside of relation where I can match pat_id of process history model with persons model.

I just found that I was actually searching for relationship with composite key but this feature is not provided in laravel. It can be solved by using https://github.com/topclaudy/compoships package.

ProcessHistory::with(['own'=>function($query) use ($param){
return $query->where('pat_id',$param);
}])->get();

Related

How to improve poor performance of EF Core SQL query that sorts on a child collection

My issue is with the queries that EF Core generates for fetching ordered items from a child collection of a parent.
I have a parent class which has a collection of child objects. I'm using Entity Framework Core 5.0.5 (code first) against a SQL Server database. I've tried to boil down the scenario, so let's call it an Owner with a collection of Pets.
I often want a list of owners with their oldest pet, so I'll do something like
Context.Owners
.Select(owner =>
new {
Owner = owner,
OldPet = owner.Pets.OrderBy(pet => pet.Age).LastOrDefault()
})
.Where(owner.Id == 1);
This worked fine before (on ef6) and works functionally now. However, the issue I have is that now EF Core translates these sub collection queries into something apparently cleverer, something like
SELECT *
FROM [Owners] AS [c]
LEFT JOIN (
SELECT *
FROM (
SELECT [c0].[Id] ... , ROW_NUMBER() OVER(PARTITION BY [c0].[OwnerId] ORDER BY [c0].[Age] DESC) AS [row]
FROM [Pets] AS [c0]
) AS [t]
WHERE [t].[row] <= 1
) AS [t0] ON [c].[Id] = [t0].[OwnerId]
The problem I'm having is that it seems to perform terribly. Looking at the execution plan it's doing a clustered index seek on the pets table, then sorting them. The 'number of rows read' is massive and the 'sorting' takes tens or hundreds of milliseconds.
The way EF6 does the same functionality seemed way more performant in this sort of scenario.
Is there a way to change the behaviour so I can choose? Or a way to rewrite this type of query such that I don't have this problem? I've tried many variations of using GroupBy etc and still have the same result.
If you are doing FirstOrDefault in projection, EF Core has to create such join, which uses Window Function ROW_NUMBER. To get desired SQL it is better to rewrite your query to be more predictable for LINQ translator:
var query =
from owner in Context.Owners
from pet in owner.Pets
where owner.Id == 1
orderby pet.Age descending
select new
{
Owner = owner,
OldPet = pet
}
var result = query.FirstOrDefault();

SOQL Query for Left Join for custom objects

I have a requirement to fetching data from Sales force. I need to get the data from two custom objects. I
have written query in sql can anyone help me to convert it into SOQL
SELECT ID, Name, Crop_Year__c, Targeted_Enrollment_Segments__c, Description__c, Start_Date__c,
End_Date__c from Enrollment_Program__c EP
Left Join Account_Enrollment__c AE on EP.Crop_Year__c = AE.Crop_Year__c and EP.ID =
AE.Enrollment_Program__c
where AE.Account__c = 'xyz'
As you probably know, Salesforce SOQL doesn't have explicit JOIN clauses. It does that for you implicitly based on related object fields. That means you'll have to query Account_Enrollment__c and traverse the fields to get the related Enrollment_Program__c Lookup relationship.
Another problem is Salesforce only performs joins based on primary and foreign keys, so the EP.Crop_Year__c = AE.Crop_Year__c in your query won't work.
So, with that said, you can try this:
SELECT Enrollment_Program__c, Enrollment_Program__e.Name,
Enrollment_Program__r.Crop_Year__c, Enrollment_Program__r.Targeted_Enrollment_Segments__c,
Enrollment_Program__r.Description__c, Enrollment_Program__r.Start_Date__c,
Enrollment_Program__r.End_Date__c
FROM Account_Entrollment_Program__c WHERE Account__c = 'zyz'
If you know beforehand what the Crop_Year__c value is, you can just add this to your query:
AND Crop_Year__c=:year AND Enrollment_Program__c.Crop_Year__c=:year
Some details on the queries:
The __r suffix is how you get the lookup object addressed in the query. If you are interested only in the id, you can use __c.
The :year is how you pass the parameter year to the query. If you want to append it as text you can just use ... Crop_Year='+ year + '.

Best rules to get data with Contain

In CakePHP 3 ORM has changed and I can't find the proper way to select needed data from the database.
In CakePHP 2, I use contain('User.name','User.id'), but In CakePHP 3 this code doesn't work.
So how can I select only id and name from User?
The code:
$query = $data->find()->contain(['Users'])->execute()->fetchAll('assoc');
// I want only user.id and user.name.
$articles = $this->Model->find()
->select(['fields_you_want_from_this_Model'])
->contain(['Assoc_Model' => function($q) {
return $q
->select(['fields_you_want_from_the_associated_model']);
}]);
U must take a look about this page: http://book.cakephp.org/3.0/en/orm/query-builder.html#passing-conditions-to-contain
In certain case you must use autoFields method.
Be carefull with contain when u select few fields in the callable, u always have to select the foreign key also:
When you limit the fields that are fetched from an association, you must ensure that the foreign key columns are selected. Failing to select foreign key fields will cause associated data to not be present in the final result.

Populate a column in a junction table Transact-SQL

I have two tables with a many-to-many relationship.
The relevant part of the tables look like this:
Filmlager [ProgramID, Type]
Genre [GenreID, GenreTitle]
Since there's a many-to-many relationship I've created a junction table looking like this:
ProgramGenre [ProgramID, GenreID, GenreOrder]
Now I want to set the value 1 in the GenreOrder column where Filmlager.Type=Genre.GenreTitle
So far I've managed to get the ProgramID and GenreID where I want to update the GenreOrder by using the following query:
SELECT p.ProgramID, p.GenreID
FROM ProgramGenre p, Filmlager f, Genre g
WHERE p.ProgramID = f.ProgramID
AND p.GenreID = g.GenreID
AND f."Type"= g.GenreTitle;
I'm not sure how to proceed from here. The part I can't figure out is how to compare the combination of two columns (the result from the query above) with ProgramID and GenreID in the ProgramGenre table. I've tried using nested queries without success.
I'm using Transact-SQL in Microsoft SQL Server Management Studio
Thanks in advance!
Just do an update:
UPDATE p SET GenreOrder = 1
FROM ProgramGenre p
JOIN Filmlager f ON p.ProgramID = f.ProgramID
JOIN Genre g ON p.GenreID = g.GenreID
WHERE f."Type"= g.GenreTitle;

How do I query in GQL using the entity key

How do I write a query against the entity key using GQL in the Google App Engine Data Viewer ?
In the viewer, the first column (Id/Name) displays as name=_1, in the detail view it shows the key as
Decoded entity key: Programme: name=_1
Entity key: agtzcG9...................
This query does not work:
SELECT * FROM Programme where name = '_1'
You can use the entity's key to retrieve it:
SELECT * FROM Programme where __key__ = KEY('agtzcG9...................')
And, you should be able to query using the name similarly:
SELECT * FROM Programme where __key__ = KEY(Programme, '_1')
Note that this is not something that you would want to do in your AppEngine application; as Nick notes in his comment, it is a huge waste of time. Really, this example is only good to show you how to query by Key in the Admin console.
For numeric IDs, a form similar to the query-by-name works:
SELECT * from Programme where __key__ = KEY('Programme', 1234567)
I found this form especially useful in the Admin Console.
You don't need to query to get an entity by key at all - you can simply fetch the entity by its key. In Python, you can do this with MyModel.get_by_key_name('_1'). This is 3 to 5 times faster than Adam's suggestion of using a query.
When querying by key, you need to match the key exactly, including the parent and not just the ID or name. Of course, if the parent is null, as in the example above, the ID or Name and the type of entity is enough.
If you have the already encoded entity key, you can just use that like:
SELECT * FROM Programme where __key__ = KEY('agtzcG9...................')
For the simple example above,
SELECT * FROM Programme where __key__ = KEY('Programme', '_1')
will do, but if your key has a parent, like
Paren: id=123
Then the query would be
SELECT * FROM Programme where __key__ = KEY('Paren', 123, 'Programme', '_1')
If the parent itself has a parent, you need to add that too. For more details see the official GQL documentation.
There does not appear to be a way to select everything with the same ID or name regardless of parent.
Just a quick note on this: When I use any quotes around any of the args in KEY, the call fails (in the admin console I get the error popup).
For example, for type "mytype" with ID/Name 12345, this does NOT work:
SELECT * FROM mytype WHERE __key__ = KEY('mytype', '12345')
But this does:
SELECT * FROM mytype WHERE __key__ = KEY(mytype, 12345)

Resources