i'm going to select user detail as table structure.
Table user columns {user_id, region_id, user_name}
Table region columns {region_id, country_id }
Table country columns {country_id, country_name }
I've join table model as
db.user.hasOne(db.region, {foreignKey:"region_id", targetKey:"region_id"});
db.region.hasOne(db.country,{ foreignKey :"country_id", targetKey:"country_id" });
db.user.hasOne(db.country,{through:db.region,otherKey :"country_id", foreignKey :"user_id" });
Now i am going to select user detail contain region name and contain country name here is my controller
models.user.findAll(
{
include: [
{
model: models.region,
model: models.country
}
]
});
but this show user not associate with country
Please save me
it should be multi level join as your schema
models.user.findAll(
{
include: [
{
model: models.region,
include:[{model:models.country}]
}
]
});
provided that user belongsTo region , region belongsTo country
you can search more about relationships some examples are
One-to-one relationship: You, as a User, can have one (hasOne)
Profile. And of course the inverse also applies. Profile (belongsTo) a
User. A user can't have more than one profile and a profile can't
belong to multiple users.
Also
We can define the inverse of a hasOne relationship using the belongsTo method.
Related
So i have a table with vehicles in my DB, each vehicle has a relationship with an user in the Users table and each user has a company value. I need to get all the vehicles that have a user that has an specific compay value.
example: query = vehicles.users(company = company)
If the relationship between vehicles and users is ManyToMany, and the relationship between company and user is OneToOne, you could do:
query = vehicles.objects.filter(user__company__id="my_company_id")
Actually I'm confused for the case, which relation fits best for my case, and in my opinion the best one is to have a table with 3 primary keys.
To be more specific.
I have a Person model in one of my db's, which has structure like
Person:
Id,
FirstName,
LastName,
...
And the other model Department, which has structure mentioned below
Department:
Id,
Name,
Description,
...
And goal is to set up Editors of schedule for each department and add also admins, whioch will approve requested schedules from editors. Editors and Admins are from same Person table, and if to assume, we need to map some Persons and department with some type.
I'm thinking about to have a mapping table with structure
PersonID,
DepartmentID,
Type (editor or admin)
And not sure, which relation fits best for this. If to have belongsToMany relation here with primary keys PersonID and DepartmentID, we will face an issue, because same Person possibly can be as editor and as admin for one single department. I have MS SQL server as a db.
Any suggestions will be appreciated
you can define many to many relations and use wherePivot method to select by pivot table Type column:
// Department model
public function admins()
{
return $this->belongsToMany(Person::class)->wherePivot('type', 'admin');
}
public function editors()
{
return $this->belongsToMany(Person::class)->wherePivot('type', 'editor');
}
// Person model
public function departmentsWhereIsAdmin()
{
return $this->belongsToMany(Department::class)->wherePivot('type', 'admin');
}
public function departmentsWhereIsEditor()
{
return $this->belongsToMany(Department::class)->wherePivot('type', 'editor');
}
// Note: we use methods names without parentheses
// usage for department
$department = Department::first(); // for example
dump($department->admins);
dump($department->editors);
// usage for person
$person = Person::first(); // for example
dump($person->departmentsWhereIsAdmin);
dump($person->departmentsWhereIsEditor);
we have a problem to query our database in a meant-to-be fashion:
Tables:
employees <1-n> employee_card_validity <n-1> card <1-n> stamptimes
id id id id
employee_id no card_id
card_id timestamp
valid_from
valid_to
Employee is mapped onto Card via the EmployeeCardValidity Pivot which has additional attributes.
We reuse cards which means that a card has multiple entries in the pivot table. Which card is right is determined by valid_from/valid_to. These attributes are constrained not to overlap. Like that there's always a unique relationship from employee to stamptimes where an Employee can have multiple cards and a card can belong to multiple Employees over time.
Where we fail is to define a custom relationship from Employee to Stamptimes which regards which Stamptimes belong to an Employee. That means when I fetch a Stamptime its timestamp is distinctly assigned to a Card because it's inside its valid_from and valid_to.
But I cannot define an appropriate relation that gives me all Stamptimes for a given Employee. The only thing I have so far is to define a static field in Employee and use that to limit the relationship to only fetch Stamptimes of the given time.
public static $date = '';
public function cardsX() {
return $this->belongsToMany('App\Models\Tempos\Card', 'employee_card_validity',
'employee_id', 'card_id')
->wherePivot('valid_from', '>', self::$date);
}
Then I would say in the Controller:
\App\Models\Tempos\Employee::$date = '2020-01-20 00:00:00';
$ags = DepartmentGroup::with(['departments.employees.cardsX.stamptimes'])
But I cannot do that dynamically depending on the actual query result as you could with sql:
SELECT ecv.card_id, employee_id, valid_from, valid_to, s.timestamp
FROM staff.employee_card_validity ecv
join staff.stamptimes s on s.card_id = ecv.card_id
and s.stamptimes between valid_from and coalesce(valid_to , 'infinity'::timestamp)
where employee_id = ?
So my question is: is that database desing unusual or is an ORM mapper just not capable of describing such relationships. Do I have to fall back to QueryBuilder/SQL in such cases?
Do you suit your database model towards ORM or the other way?
You can try:
DB::query()->selectRaw('*')->from('employee_card_validity')
->join('stamptimes', function($join) {
return $join->on('employee_card_validity.card_id', '=', 'stamptimes.card_id')
->whereRaw('stamptimes.timestamp between employee_card_validity.valid_from and employee_card_validity.valid_to');
})->where('employee_id', ?)->get();
If your Laravel is x > 5.5, you can initiate Model extends the Pivot class I believe, so:
EmployeeCardValidity::join('stamptimes', function($join) {
return $join->on('employee_card_validity.card_id', '=', 'stamptimes.card_id')
->whereRaw('stamptimes.timestamp between employee_card_validity.valid_from and employee_card_validity.valid_to');
})->where('employee_id', ?)->get();
But code above is only translating your sql query, I believe I can write better if I know exactly your use cases.
I am trying to create the database structure for the locations of a retail company where the base is store and a district is a group of stores grouped geographically and so on. From largest to smallest(area wise) it goes:
Area -> Region -> District -> Store
Each level has the same basic columns:
ID
Name
LeaderID
CreatedOn
UpdatedOn
Active
Is it better to have each of these levels in their own table, or condense it down to one 'Locations' table with a 'ParentLocation' column? Would there be a noticeable performance hit since going up the hierarchy will required joining on the same table multiple times?
You need a table for level with parent child relationship, as long you create proper index for the join fields the performance wont be affected.
Area: { area_id (pk), area }
Region: { region_id (pk), area_id (fk), region }
District: { district_id (pk), region_id (fk), district }
Then your Store Table will have a reference to the district the more specific location.
Store: { store_id (pk), district_id (fk), <other store fields>}
If you want Stores from some specific Area you join all tables
SELECT S.*
FROM Stores S
JOIN District D ON S.distric_id = D.distric_id
JOIN Region R on D.region_id = R.region_id
JOIN Area A on R.area_id = A.area_id
WHERE A.area = 'some area'
EDIT: Maybe I understand the geography backwards. For my example I assume Area is the bigger geometry and District are the smaller one.
It is better to have one table of Locations and have a parent location column.
As for the traversal of the tree there are many ways to do this to handle different scenarios. The basic answer will be it depends on how much data you have in the table and how you are using it.
Some of the different options that you have with this are:
Create a path index (e.g. AreaId|RegionId|District )
Recursively traverse the tree
Self join
I'm sure there are others as this isn't a complete list but what you're going to have to do is create some test metrics and then decide on what's best for your problem.
I'm creating a database to track my students' participation in classes. This is what I've set up so far. I'm working in Access 2007.
Participant Master table - name, contact info, enrolled class, enrolled semester. Enrolled class (Class A, Class B, Class C) and enrolled semester (Semester 1, Semester 2) are defined in tables. Primary key is an autoincrement number but students all get a school ID number (ParticipantID).
Query1 pulls name & address for students enrolled in class A, semester 2
(SELECT name, address FROM ParticipantMaster WHERE EnrClass = "Class A" and EnrSem = "Semester 2"). The query works.
DailySessionLog is a table to represent each daily class. Includes fields for date, instructor name (check from list), discusssion topic (check from list).
Now I want to link DailySessionLog to Query1 -- letting me check off every day whether a student was there for None, Partial, Half, or Full session that day. I'm having trouble linking these and creating a subform. Any help?
I tried having a ParticipantID field in DailySessionLog which I linked to ParticipantID in Query1. It doesn't recognize if it's a one:one or :many relationship. If I go ahead and create a subform using the Access wizard it treats the Participant data as the "higher" form and the DailySessionLog data as the "sub" form. I want it to be the other way around.
Thanks for helping!
To create a one-to-one or one-to-many relationship, you should link DailySessionLog to ParticipantMaster rather than to Query1. You would then create a query to show the daily session logs of a given class for a given semester. Example:
SELECT {field list} FROM ParticipantMaster INNER JOIN DailySessionLog ON {join expression} WHERE ParticipantMaster.EnrClass = "Class A" AND ParticipantMaster.EnrSem = "Semester 2"
However, it would be better to use variable parameters rather than hard-coded strings. Example:
SELECT {field list} FROM ParticipantMaster INNER JOIN DailySessionLog ON {join expression} WHERE ParticipantMaster.EnrClass = [ClassName] AND ParticipantMaster.EnrSem = [SemesterName]
Or, to use a value from a control on an open form:
SELECT {field list} FROM ParticipantMaster INNER JOIN DailySessionLog ON {join expression} WHERE ParticipantMaster.EnrClass = [Forms]![FormName]![ClassControlName] AND ParticipantMaster.EnrSem = [Forms]![FormName]![SemesterControlName]
EDIT
Actually, you want to use this AND xQbert's idea, so, with table names like this for brevity:
Participants (a.k.a. ParticipantMaster)
Sessions (a.k.a DailySessionLog)
ParticipantSession (a.k.a. Participant_daily_session_log)
the first query would be more like this:
SELECT {field list}
FROM
Participants
INNER JOIN ParticipantSession ON Participant.ID = ParticipantSession.ParticipantID
INNER JOIN Sessions ON ParticipantSession.SessionID = Session.ID
Where do you intend the database to "Store" the participation?
I think the problem is you need another table: a Particpiant_Daily_sessioN_log which would store the results of your daily log for each student participation.
Think about the table dailysessionlog you don't want instructor name, topic and date listed for EACH student do you?
So what you have is a many students may attend class and a class may have many students. This means you have a many to many which needs to be resolved before access can figure out what you want to do.
Think of the following tables:
Participant (ParticipantID)
Class (ClassID)
Session (SessionID, ClassID)
ClassParticipants (ClassId, ParticipantID, Semester, year
SessionParticipants (SessionID, ClassID, ParticipantID)