I have a function on a model:
public function getAll()
{
$allusers = DB::table('users')->join('countries', 'countries.id', '=', 'users.country_id')->get();
return $allusers;
}
This works fine except the id of the user is replaced by the id of the country:
array(2) { [0]=> object(stdClass)#201 (20) { ["id"]=> int(42) ["name"]=> string(11) "Jim Elliott" ... and so on
The ID should be 1 as the country_id is 42.
Should I add an alias for the country ID and is so how? Or can I restrict the fields of the countries table to just be the country and flag?
In the end I cheated with a view in which I linked the 2 tables and gave an alias to the country ID. Not an elegant solution but it has worked. I am sure there is a proper way to do it in Laravel without a view, so my function then became:
$allusers = DB::table('v_users')->get();
return $allusers;
$users = DB::table('users')->join('countries', 'countries.id', '=', 'users.country_id')
->select(DB::raw(
"SELECT users.*,countries.*, users.id AS 'user_id',
countries.id AS 'country_id'"
);
Related
How do I join the Resources Table to the Resources_role table where resources_id column is common in both table. Below is my code to fetch the Resources table using the Role_id, however I want all the records from the resources table that share the same resources_id column with the Resources_Role to be fetched.
How do I do this join please, below is my code
public IQueryable <Resources_Role> FindResourceByRoleID(int RoleId)
{
var roleid = from p in context.Resources_Role
select p;
roleid = roleid.Where(p => p.ROLE_ID==(RoleId));
return roleid;
}
The thing you should watch is the method return type. Depending on what you want to return, you should adjust the return type based on result set from JOIN query you're using:
// returning resources
public IQueryable<Resources> FindResourceByRoleID(int RoleId)
{
return (from res in context.Resources
join role in context.Resources_Role
on res.resources_id equals role.resources_id
where res.ROLE_ID == RoleId
select res);
}
// returning resource role
public IQueryable<Resources_Role> FindResourceRoleByRoleID(int RoleId)
{
return (from role in context.Resources_Role
join res in context.Resources
on role.resources_id equals res.resources_id
where res.ROLE_ID == RoleId
select role);
}
Those queries above will produce SQL statements as shown below:
-- returns resources
SELECT t0.* FROM Resources AS t0 INNER JOIN Resources_Role AS t1
ON t0.resources_id = t1.resources_id
WHERE t0.ROLE_ID = #RoleId
-- returns resources role
SELECT t0.* FROM Resources_Role AS t0 INNER JOIN Resources AS t1
ON t0.resources_id = t1.resources_id
WHERE t1.ROLE_ID = #RoleId
Note: Cannot implicitly convert type System.Linq.IQueryable<Resource> to System.Linq.IQueryable<Resources_Role> is self-explanatory: it occurs because your query returns IQueryable<Resource> but the method return type set to IQueryable<Resources_Role>. You must adjust the query to return IQueryable<Resources_Role> instead.
After you've got your roleId from your method, you could do something like the following to return a Resource:
var resources = from resource in context.Resources
where resource.ROLE_ID == roleId
join resource_role in context.Resources_Role
on resource.resources_id equals resource_role.resource_id
select resource;
To get a Resource_Role you could do something like this:
var resource_role = from role in context.Resource_Roles
join resource in context.Resources_Role.Where(resource_role => resource_role.ROLE_ID == roleId)
on role.resources_id equals resource.resource_id
select role;
I'm afraid I don't have a working MVC env to test any of this in atm, but it should be a good starting point.
I have the following structure:
Buro->hasOne->Address->hasOne->City->hasOne->State
Buro->hasOne->Category
and
Order->hasOne->Address->hasOne->City->hasOne->State
Order->hasOne->Category
and
Category->hasMany->Orders and Category->hasMany->Buros
I have a "One-To-Many" polymorphic relation between addresses in one side and Buro/Orders in the other side. There is just One address for a buro and just one adddress for an order, therefor I couls use [0] to get the first the first and only one element in a collection.
Address class
class Address extends Model
{
...
public function addressable()
{
return $this->morphTo();
}
...
}
Büro class
class Buro extends Model
{
....
public function addressable()
{
return $this->morphMany('App\Address', 'addressable');
}
...
}
Order class
class order extends Model
{
....
public function addressable()
{
return $this->morphMany('App\Address', 'addressable');
}
...
}
Now I am building a form in the frontend with a SELECT field in order to select just from the Buros that operate in the same State where the order was placed.
Using ELOQUENT I did this:
$all_bueros = Buero::where('category_id', $order->category_id)
->where('title', $order->client->addressable[0]->city->state->title) // <- Look at this "title" column name
->pluck('title', 'id')->all();
The problem here is that the "Title" column name is not in "Buros" table but three tables away. Exactly in: buros.addresses.city.state.title
I have tried these syntaxes but no one worked:
->where('buros.addresses.city.state.title', $order->client->addressable[0]->city->state->title) // as object notation
and
->where('buros->addressable[0]->cities->state->title', $order->client->addressable[0]->city->state->title) // using the relation
I used the query builder but there is even more messy:
$buros = DB::table('buros')
->join('categories', 'categories.id', '=', $order->category_id)
->join('addresses', 'addresses.addressable_id', '=', $order->id, 'AND','addresses', 'addresses.addressable_type', '=', 'buros') //two points to join the table
->join('cities', 'addresses.city_id', '=', 'cities.id')
->join('states', 'cities.states', '=', 'states.id')
->select('buros.title', 'buros.id')
->where('states.title', '=', $order->client->addressable[0]->city->states->title)
->get();
My problem is how to join a table in two points since there is a polymorphic relation. Because I need to join the Address Table in the "Buro-column" (addressable_type) and in the Buro-id column (addressable_id)
Any help will be appretiate
For example I have follow domains:
class Company {
String name
}
class Employee {
String firstName
String secondName
Company company
}
And I try to get all employees where company name is 'M$oft'
Employee.where {
eq 'company.name', 'M$oft'
}.list()
Got:
could not resolve property: company.name of: myapp.Employee
Also I try this:
Employee.where {
createAlias('company', 'c')
eq 'c.name', 'M$oft'
}.list()
Got:
could not resolve property: c of: myapp.Employee
I know about:
Employee.where {
company.name == 'M$oft'
}
but it's not appropriate for me.
I just want to know: is it possible do it via where clause with usage of string names of fields?
Use next syntax:
Employee.where {
company{
eq 'name', 'M$oft'
}
}.list()
And don't forget to use ' ' with strings that have $. Maybe some unexpected result.
I have an entity, Student, defined in Student.groovy as:
#EqualsAndHashCode(includes = ['id'])
class Student {
Long id
String name
String type
University university
static mapping = {
university column : 'UNIVERSITY_ID'
}
}
and a University entity, defined in University.groovy as:
class University {
Long id
String name
static mapping = {
id column : 'id', generator : 'assigned'
}
}
I've been trying to switch from calling
Student.list(sort: ..., order: ...)
to calling:
Student.findAll("from Student s where type = :type ", [type : 'T'], [ sort : 'name' ])
This fails to order correctly by the name field. The previous version, using list worked fine.
I've also tried calling something like
Student.findAll(sort : 'name') { type == "T" }
which worked fine like this, but when trying to sort by the university.name
Student.findAll(sort : 'university.name') { type == 'T" }
it raised an error regarding the university.name field not being found.
Anybody have any idea on how to do this properly?
Thank you.
Use executeQuery instead of findAll - they should function the same, but I've found that executeQuery is for some reason a more direct caller of the HQL, and findAll fails or returns unexpected results in some cases.
So that first query would be
Student.executeQuery(
'select s from Student s where s.type = :type order by s.name',
[type : 'T'])
and ordering by university name would be
Student.executeQuery(
'select s from Student s where s.type = :type order by s.university.name',
[type : 'T'])
I like HQL and tend to use it a lot, but it couples you to Hibernate and relational databases - if you want to switch to a NoSQL database these queries will fail. Criteria queries, "where" queries and finders all use criteria queries internally, and those are converted to native query API calls by the GORM implementation.
The equivalent criteria queries would be
Student.withCriteria {
eq 'type', 'T'
order 'name', 'asc'
}
and
Student.withCriteria {
eq 'type', 'T'
university {
order 'name', 'desc'
}
}
Some unrelated notes:
You shouldn't use id in equals or hashCode calculations; if you have a persistent Student and a new non-persistent instance with the same name, type, and University, they should be considered equal, but since the non-persistent instance's id will be null they'll be considered different.
You don't need to specify the id property - Grails adds it and the version field to the bytecode via an AST transformation during compilation.
There's no need to map the column name of the university property to 'UNIVERSITY_ID' - that's what it would be anyway.
You can omit the redundant column setting in the id mapping.
Here's the Student class with cruft removed:
#EqualsAndHashCode(includes = ['name', 'type', 'university'])
class Student {
String name
String type
University university
}
and University:
class University {
String name
static mapping = {
id generator: 'assigned'
}
}
I want to return top 1 CustomerId from my table like this:
string nxtCustId = db.ExecuteStoreQuery<string>("SELECT TOP 1 CustId FROM CustomerMaster WHERE Id >=(SELECT Max(Id) FROM CustomerDetail ) ORDER BY Id ").ToString();
But it returns System.Data.Objects.ObjectResult1[System.String]
I want to do it with only ExecuteStoreQuery OR ExecuteStoreCommand.
string nxtCustId = db.ExecuteStoreQuery<string>(
"SELECT TOP 1 CustId FROM CustomerMaster WHERE Id >=(SELECT Max(Id) FROM CustomerDetail ) ORDER BY Id ")
.FirstOrDefault();
Having said that, don't create "IDs" this way; it's not multi-user safe. Use an autoincrement field or a generator/sequence.