I'm trying to build an NSPredicate to satisfy a given relationship. My data model has the following: University -> College -> Classrooms - ClassroomType
A university object has 1 to many colleges.
A college object has 1 to many classrooms.
Each classroom has a given classroom type with a specified property
i'm interested in.
That property is called typeDescription I want to build a query that can give me all universities that have a typeDescription equal to the value "computerlab". The objects that I have available to me are a list of Universities. I'm pretty sure that I'll need to construct an NSPredicate SUBQUERY but I'm not quite sure no how to build this to satisfy my requirements. If anyone has any input on the right way to build this query it would be much appreciated.
For one-to-many-to-many relationships, you need to nest two SUBQUERY clauses:
NSPredicate(format:"SUBQUERY(colleges, $c, SUBQUERY($c.classrooms, $room, $room.classroomType.typeDescription == %#).#count > 0).#count > 0","computer lab")
Related
I would like some help as the data structure in Firebase. I've read the API guide and some blog articles like these:
Queries, Part 1: Common SQL Queries Converted for Firebase
Firebase: Now with more querying!
Denormalizing Your Data is Normal
I'm leaving SQL (MySQL and SQLite specifically) and trying to migrate to Firebas. I would like to know how to structure these tables and relationships for a structured JSON in Firebase.
Relationship 1-1; 1 - N; N - N;
I'm sending a picture of an example database containing some relationships, could you give me this support would look like this in the database you? Remembering that I need to consult with the data about the same as would query in SQL.
This is my Database:
I'll take a shot at this...
First and foremost, Firebase is not a relational database so it should not be thought of in those terms. However, you can craft 'relationships' between data that (for an end user) feels 'relational'
Let's use a Departments and Employees-like example. A department can have many employees and those employees belong to that department.
departments
dept_00
dept_name: "Bridge"
dept_01
dept_name: "Engineering"
dept_02
dept_name: "Medical"
crew
crew_00
crew_name: "Kirk"
in_dept: "dept_00"
crew_01
crew_name: "Scotty"
in_dept: "dept_01"
crew_02
crew_name: "Bones"
in_dept: "dept_02"
crew_04
crew_name: "Spock"
in_dept: "dept_00"
With this structure, a query can be performed for crew that are bridge members: here's an ObjC snippit
Firebase *ref = [myRootRef childByAppendingPath:#"crew"];
FQuery *q1 = [ref queryOrderedByChild:#"in_dept"];
FQuery *q2 = [q1 queryEqualToValue:#"dept_00"];
[q2 observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
NSLog(#"%#", snapshot.value);
}];
This will return the crew_00 (Kirk) and the crew_04 (Spock) nodes.
Note the disassociation between the data (Bridge, Engineering) and the node name (dept_00, dept 01). This allows the data to be modified without breaking 'links' between them. So I could rename 'Engineering' to 'Scotty's Hideaway' and everything will continue to work. Those 'random' node names would be generated by a push() in firebase or ChildByAutoId (objc)
Likewise, if we know the crew member name (Bones) we could query for that specific node to return that he belongs to dept_02 (Medical).
You could expand beyond this in cases where say, Spock and Bones belongs to several different departments, say Bridge and Engineering, by adding another node to track which departments the crew member belongs to:
belongs_to
crew_02
dept_00: true
dept_02: true
crew_04
dept_00: true
dept_01: true
Here, crew_02 (Bones) is now in the Medical and Bridge departments (much to Spocks dismay) and crew_04 (Spock) is now in the Bridge and Engineering Department. With this added belong_to node, the in_dept child nodes could be removed from the crew node.
That should cover one to one, one to many and many to many
I am struggling with a basic problem. i am using cake php 2.5. i try to apply the find query in the company model and receiving all the data from companies and with its associations, but i only want to receive the data from company table and want to exclude the data from rest of relationships, can anyone help me with this. below are my queries.
$this->loadModel('Company');
$fields=array('id','name','logo','status');
$conditions=array('status'=>1);
$search_companies = $this->Company->find('first',
compact(array('conditions'=>$conditions,'fields'=>$fields)));
print_r($search_companies);die();
echo json_encode($search_companies);die();
With out seeing your data output, I am just going to take a stab at the problem.
Inside your $search_companies variable you are getting a multidimensional array probably with the other values of the other tables.
Why not just select the one array:
$wantedData = $search_companies['Company'];
// The key Company (which is the model) should be the data you are wanting.
Try setting model's recursive value to -1
$this->Company->recursive = -1;
$search_companies = $this->Company->find('first',
compact(array('conditions'=>$conditions,'fields'=>$fields)));
With this you will not fire the joins queries and therefore you only retrieve model's information.
Cakephp provide this functionality that we can unblind few/all associations on a any model. the keyword unbindModel is used for this purpose. inside the unblindModel you can define the association type and model(s) name that you want to unblind for that specific association.
$this->CurrentModelName->unbindModel(array('AssociationName' => array('ModelName_Youwwant_unblind')));
Background
I'm faced with the following problem, relating to three tables
class_sectors table contains three categories of classes
classes table contains a list of classes students can attend
class_choices contains the first, second and third class choice of the student, for each sector. So for sector 1 Student_A has class_1 as first choihce, class_3 as second choice and class_10 as third choice for example, then for sector 2 he has another three choices, etc...
The class_choices table has these columns:
kp_choice_id | kf_personID | kf_sectorID | kf_classID | preference | assigned
I think the column names are self explanatory. preference is either 1, 2 or 3. And assigned is a boolean set to 1 once we have reviewed a student's choices and assigned them to a class.
Problem:
Writing an sql query that tells the students what class they are assigned to for each sector. If their class hasn't been assigned, it should default to show their first preference.
I have actually got this to work, but using two (very bloated??) sql queries as follows:
$choices = $db -> Q("SELECT
*, concat_ws(':', `kf_personID`, `kf_sectorID`) AS `concatids`
FROM
`class_choices`
WHERE
(`assigned` = '1')
GROUP BY
`concatids`
ORDER BY
`kf_personIDID` ASC,
`kf_sectorID` ASC;");
$choices2 = $db -> Q("SELECT
*, concat_ws(':', `kf_personID`, `kf_sectorID`) AS `concatids`
FROM
`class_choices`
WHERE
`preference` = '1'
GROUP BY
`concatids`
HAVING
`concatids` NOT IN (".iimplode($choices).")
ORDER BY
`kf_personID` ASC,
`kf_sectorID` ASC;");
if(is_array($choices2)){
$choices = array_merge($choices,$choices2);
}
Now $choices does have what I want.
But I'm sure there is a way to simplify this, merge the two SQL queries, and so it's a bit more lightweight.
Is there some kind of conditional SQL query that can do this???
Your solution uses two steps to enable you to filter the data as needed. Since you are generating a report, this is a pretty good approach even if it looks a bit more verbose than you might like.
The advantage of this approach is that it is much easier to debug and maintain, a big plus.
To improve the situation, you need to consider the data structure itself. When I look at the class_choices table, I see the following fields: kf_classID, preference, assigned which contain the key information.
For each class, the assigned field is either 0 (default) or 1 (when the class preference is assigned for the student). By default, the class with preference = 1 is the assigned one since you display it in the report when assigned=0 for all the student's class choices in a particular sector.
The data model could be improved by imposing a business rule as follows:
For preference=1 set the default value assigned=1. When the class selection process
takes place, and if the student gets assigned the 2nd or 3rd choice, then preference 1 is unassigned and the alternate choice assigned.
This means a bit more code in the application but it makes the reporting a bit easier.
The source of the difficulty is that the assignment process does not explicitly assign the 1st preference. It only updates assigned if the student cannot get the 1st choice.
In summary, your SQL is good and the improvements come from taking another look at the data model.
Hope this helps, and good luck with the work!
I've got records in my MySQL projects database that have several boolean flags to help me sort the data. I have 3 categories planning, landscape, and environmental and 4 classes (or subcategories) for each category; industrial, government, education, residential.
My goal is to use ColdFusion to create and store the project_id numbers in an array of some kind that will basically have the projects sorted by category and class. That way I can grab just the industrial projects in the planning category and construct a link to that project.
So, the first position in the array would be planning and inside that first position would be the 4 classes, then, within that would be all of the project_id numbers that returned true for those particular criteria.
The logic I'm looking to create goes like this...
Loop over the query result, if planning = true and industrial = true, place the project id # into the planning array inside the industrial array.
How can I use <cfloop> to loop over the list of project records, recognize the category and class flags and construct a clean and usable dataset? Can this be handles in the query in some way?
Figure out the desired data structure
look at your existing data structure
figure out the algorithm to translate from one to the other
You may cfloop the query, and use a large cfswitch (or large set of if-then-else) to figure out how you want to store the id in your desired data structure. Or if you can map the class/category name as a struct key, then it might be easier.
Or you may use cfoutput group="" if it helps (cfloop group="" is available on in CF10+)
Finally, maybe you don't even need the data structure, just use Query of Queries wherever you need.
You may be able to utilize the Underscore.cfc library for this. For example, you could use the filter function to extract an array of structs representing the query rows you want:
planningArray = _.filter(queryResult, function(row){
return (row.planning == true && row.industrial == true);
});
We want to set up a directory of all the organizations working with us. They are incredibly diverse (government, embassy, private companies, and organizations depending on them ). So, I've resolved to create 2 tables. Table 1 will treat all the organizations equally, i.e. it'll collect all the basic information (name, address, phone number, etc.). Table 2 will establish the hierarchy among all the organizations. For instance, Program for illiterate adults depends on the National Institute for Social Security which depends on the Labor Ministry.
In the Hierarchy table, each column represents a level. So, for the example above, (i)Labor Ministry - Level1(column1), (ii)National Institute for Social Security - Level2(column2), (iii)Program for illiterate adults - Level3(column3).
To attach an organization to an hierarchy, the user needs to go level by level(i.e. column by column). So, there will be at least 3 situations:
If an adequate hierarchy exists for an organization(for instance, level1: US Embassy), that organization can be added (For instance, level2: USAID).--> US Embassy/USAID, and so on.
How about if one or more levels are missing? - then they need to be added
How about if the hierarchy need to be modified? -- not every thing need to be modified.
I do not have any choice but working by level (i.e. column by column). I does not make sense to have all the levels in one form as the user need to navigate hierarchies to find the right one to attach an organization.
Let's say, I have those queries in my repository (just that you get the idea).
Query1
var orgHierarchy = (from orgH in db.Hierarchy
select orgH.Level1).FirstOrDefault;
Query2
var orgHierarchy = (from orgH in db.Hierarchy
select orgH.Level2).FirstOrDefault;
Query3, Query4, etc.
The above queries are the same except for the property queried (level1, level2, level3, etc.)
Question: Is there a general way of writing the above queries in one? So that the user can track an hierarchy level by level to attach an organization.
In other words, not knowing in advance which column to query, I still need to be able to do so depending on some conditions. For instance, an organization X depends on Y. Knowing that Y is somewhere on the 3rd level, I'll go to the 4th level, linking X to Y.
I need to select (not manually) a column with only one query that takes parameters.
=======================
EDIT
As I just said to #Mark Byers, all I want is just to be able to query a column not knowing in advance which one. Check this out:
How about this
Public Hierarchy GetHierarchy(string name)
{
var myHierarchy = from hierarc in db.Hierarchy
where (hierarc.Level1 == name)
select hierarc;
retuen myHierarchy;
}
Above, the query depends on name which is a variable. It mighbe Planning Ministry, Embassy, Local Phone, etc.
Can I write the same query, but this time instead of looking to much a value in the DB, I impose my query to select a particular column.
var myVar = from orgH in db.Hierarchy
where (orgH.Level1 == "Government")
select orgH.where(level == myVariable);
return myVar;
I don't pretend that select orgH.where(level == myVariable) is even close to be valid. But that is what I want: to be able to select a column depending on a variable (i.e. the value is not known in advance like with name).
Thanks for helping
How about using DynamicQueryable?
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Your database is not normalized so you should start by changing the heirarchy table to, for example:
OrganizationId Parent
1 NULL
2 1
3 1
4 3
To query this you might need to use recursive queries. This is difficult (but not impossible) using LINQ, so you might instead prefer to create a parameterized stored procedure using a recursive CTE and put the query there.