How to get 2 or more records per unique column value in ActiveRecord?
Given:
Name | School
Jonathan | Sunshine College
Dylan | Sunshine College
Matt | Sunshine College
Joseph | Sunshine College
Stephen | Greenville School
Phil | Greenville School
Warren | Greenville School
JohnPaul | Greenville School
then if I wanted to output 2 records per school, it will look like this:
Name | School
Jonathan | Sunshine College
Dylan | Sunshine College
Stephen | Greenville School
Phil | Greenville School
If I wanted 3 records per school then it'll look like this:
Name | School
Jonathan | Sunshine College
Dylan | Sunshine College
Matt | Sunshine College
Stephen | Greenville School
Phil | Greenville School
Warren | Greenville School
You can partition the data of the table by the column value you need. After that you can use a condition to tell how many records per partition you want:
Student
.from(
Student.select('*, row_number() OVER (PARTITION BY school) AS rownum')
)
.select('*')
.where('rownum < 2')
Here a way without using sql.
Student.group(:school)
.each{|student| Student.where(school: student.school)
.first(2)
.each{|result| puts "#{result.name.ljust(20, ' ')}| #{result.school}"}}
# Phil | Greenville School
# Warren | Greenville School
# Jonathan | Sunshine College
# Dylan | Sunshine College
You could uniq when you have transformed the collections of models in to a list of attributes which can be compared for equality:
MyModel.all.pluck(:first_name, :last_name).uniq
https://dba.stackexchange.com/questions/98427/normilsation-2nf-and-3nf
I've been through several questions and youtube tutorials; I understand that 2NF is removing the partial dependencies and 3NF is the transitive ones, but I can't get my head around how the following example should look like in 2NF.
studentID | studentName | courseCode | courseTitle | modCode | modTitle | credits | resultCode
My attempt is the following for 2NF:
Student
studentID | studentName | courseCode | modCode | resultCode
Course
courseCode | courseTitle
Module
modCode | modTitle | credits
Is this correct? If not, where am I going wrong and why.
The following is the 3NF:
Student
studentID | studentName | courseCode
Course
courseCode | courseTitle
Module
modCode | modTitle | credits | courseCode
Results
studentID | modCode | resultCode
Same goes for this; is this correct - if not where and why?
Ok, let's have a look at your 2NF attempt:
Student
studentID | studentName | courseCode | modCode | resultCode
Course
courseCode | courseTitle
Module
modCode | modTitle | credits
Let's talk about Student first.
Your key cannot be studentID, because the resultCode depends on studentID and courseCode (you have one result for every course). But your studentName depends only on studentID, so a part of the key (studentID,courseCode). So 2NF is violated. You need to do something like this:
Student
studentID | studentName | courseCode | modCode
Course
courseCode | courseTitle
Module
modCode | modTitle | credits
Result
studentID | courseCode | resultCode
But please keep in mind, that this respects the 2NF, but still seems not correct, because modules and courses are now completely unrelated. So try this:
Student
studentID | studentName | modCode
Module
modCode | modTitle | credits
Course
courseCode | courseTitle | modCode
Result
studentID | courseCode | resultCode
A course belongs to a module (a module has many courses) - from my point of view. This is automatically in 2NF (because the key is always just one attribute (except for the result, but there is just one non-key-attribute always depending on both key attributes), so nothing can depend on a "part" of the key). And it is in 3NF, too, because every "physical" entity has it's logical representation in the data model (more a rule of thumb than a formalism).
Now let's have a look at your 3NF attempt. I think you've got the module<->course dependency the wrong way round, but let's just concentrate on the normalization.
Student
studentID | studentName | courseCode
Course
courseCode | courseTitle
Module
modCode | modTitle | credits | courseCode
Results
studentID | modCode | resultCode
This is correct 3NF, because there is simply no other key candidate than the key itself. So there can't be any transitive dependency.
To clarify this: a key candidate is one of the many minimal sets of possible keys. In your relation you have found at least one key candidate with one element (except for the results relation). So any other key candidate cannot have more than one element. That means, that you can simply look at every single attribute and decide "can this be a key or not?" And in your example you find, that no other attribute can be a key - so it's automatically in 2NF and 3NF.
I am working on customization of openerp which is UK specific so I want to override fields of res.partner like zip and state_id. I want to use post codes instead of zip and County instead of state. There are also some apps which depend on these fields so I don't want to add new ones. The zip should remain the same but instead of zip I want it to use post code lookup for which I have the model. The state_id field should also be used as county.
The postcode model has the following fields (Data is not real)
_________________________________________________________________________
| PostCode_id | Postcode | longitude | Longitude | Town | County |
-------------------------------------------------------------------------
| 1 | 'AS34' | 53454 | 435345 | Aberdeen | Aberdeen |
.........................................................................
| ....
I want the zip to be a many2one field, when the user type the postcode it should offer auto completion. The base zip field in res.partner is of type 'char'. The state_id is a many2one field but I want to connect it to county column.
I got it. Basically setting postcode column as _rec_name solved the issue. It is also a good idea to make another table or model for county and to add foreign key in this table. This way I was able to achieve what I wanted.
Thanks anyways
I have users represented in a user table and need to design a model to associate them with state/cities/districts that they choose:
On the database side,
Each user will be associated with 1 state, 1 city and a number of districts within that state/city combination. For instance, User A can choose to be associated with "NY" and "Brooklyn" and any X number of districts in "Brooklyn" (or none).
On the view side,
I'd like to present the district choices with checkboxes so they should be able to be pulled from the database field with simple_form in Rails pretty easily.
The design of the database should make it easy to query for the user and get the associated state / city and district relations that the user has chosen.
One idea I have is to simply have a one-to-many field for districts and a district table listing all the different districts. However, is there a way to enforce that the districts have to be valid for the city/state combination on the backend using validate?
Any tips would be appreciated.
Below I have outlined the database schema I would use based on the information you have given.
Every city belongs to exactly one state.
cities
id unsigned int(P)
state_id unsigned int(F states.id)
name varchar(50)
+----+----------+---------------+
| id | state_id | name |
+----+----------+---------------+
| 1 | 33 | New York City |
| .. | ........ | ............. |
+----+----------+---------------+
See ISO 3166 for more information. You didn't ask for countries but it's trivial to add them...
countries
id char(2)(P)
iso3 char(3)(U)
iso_num char(3)(U)
name varchar(45)(U)
+----+------+---------+---------------+
| id | iso3 | iso_num | name |
+----+------+---------+---------------+
| ca | can | 124 | Canada |
| mx | mex | 484 | Mexico |
| us | usa | 840 | United States |
| .. | .... | ....... | ............. |
+----+------+---------+---------------+
Every district belongs to exactly one city.
districts
id unsigned int(P)
city_id unsigned int(F cities.id)
name varchar(50)
+----+---------+-----------+
| id | city_id | name |
+----+---------+-----------+
| 1 | 1 | The Bronx |
| 2 | 1 | Brooklyn |
| 3 | 1 | Manhattan |
| .. | ....... | ......... |
+----+---------+-----------+
See ISO 3166-2:US for more information. Every state belongs to exactly one country.
states
id unsigned int(P)
country_id char(2)(F countries.id)
code char(2)
name varchar(50)
+----+------------+------+----------+
| id | country_id | code | name |
+----+------------+------+----------+
| 1 | us | AL | Alabama |
| .. | .......... | .... | ........ |
| 33 | us | NY | New York |
| .. | .......... | .... | ........ |
+----+------------+------+----------+
Based on your information a user belongs to exactly one city. In the example data Bob is associated with New York City. By joining tables you can very easily find that Bob is in New York state and the country of United States.
users
id unsigned int(P)
username varchar(255)
city_id unsigned int(F cities.id)
...
+----+----------+---------+-----+
| id | username | city_id | ... |
+----+----------+---------+-----+
| 1 | bob | 1 | ... |
| .. | ........ | ....... | ... |
+----+----------+---------+-----+
Users can belong to any number of districts. In the example data Bob belongs to The Bronx and Brooklyn. user_id and district_id form the Primary Key which insures a user cannot be associated with the same district more than once.
users_districts
user_id unsigned int(F users.id) \_(P)
district_id unsigned int(F districts.id) /
+---------+-------------+
| user_id | district_id |
+---------+-------------+
| 1 | 1 |
| 1 | 2 |
| ....... | ........... |
+---------+-------------+
My database model does NOT enforce the rule that the districts a user belongs to must be in the city that user belongs to - in my opinion that logic should be done at the application level. If Bob moves from New York City to Baltimore I think all of his records should be deleted from the users_districts table and then add any new ones for his new city.
As for the user interface, I would have the user:
Select a country - this will auto-populate a drop down list of associated states.
Select a state - this will auto-populate a drop down list of associated cities.
Select a city - this will auto-populate a list of associated districts.
Allow the user to select any number of districts.
You will need some combination of database and application-level logic.
Here is how I would build the database fields:
users = id, <other user fields>, city_id
districts = id, <other district fields>, city_id
cities = id, name, state_id
states = id, name
And then in the application, set it up so that the user can type in one city and multiple districts, and can not edit the state (view only):
When the user types in a city - maybe through a autocomplete field - it automatically updates the read-only state field with the state of the city
When the user types in a district, list only the districts that have district.city_id == cities.id
If you don't want to restrict the district selection in the UI, you will need to enforce the district.city_id == cities.id check in your application, though I personally think that's less intuitive than doing it right in the front-end UI.
Indian States AND UT MySQL QUERY
INSERT INTO `states`
VALUES
(1,'Andhra Pradesh'),
(2,'Telangana'),
(3,'Arunachal Pradesh'),
(4,'Assam'),
(5,'Bihar'),
(6,'Chhattisgarh'),
(7,'Chandigarh'),
(8,'Dadra and Nagar Haveli'),
(9,'Daman and Diu'),
(10,'Delhi'),
(11'Goa'),
(12,'Gujarat'),
(13,'Haryana'),
(14,'Himachal Pradesh'),
(15,'Jammu and Kashmir'),
(16,'Jharkhand'),
(17,'Karnataka'),
(18,'Kerala'),
(19,'Madhya Pradesh'),
(20,'Maharashtra'),
(21,'Manipur'),
(22,'Meghalaya'),
(23,'Mizoram'),
(24,'Nagaland'),
(25,'Orissa'),
(26,'Punjab'),
(27,'Pondicherry'),
(28,'Rajasthan'),
(29,'Sikkim'),
(30,'Tamil Nadu'),
(31,'Tripura'),
(32,'Uttar Pradesh'),
(33,'Uttarakhand'),
(34,'West Bengal'),
(35,'Lakshadweep'),
(36,'Ladakh ');
I have a simple HABTM relationship Books <-> Authors and I'd like to get books by its title and name of the authors:
Book.joins(:authors)
.where("books.title ILIKE 'roman%' OR authors.name ILIKE 'pushkin%'")
.order("books.id DESC").limit(20).group("books.id")
That works perfect.
BUT if i want to sort additionally by Author name i got duplicate row for books that have many authors:
Book.joins(:authors)
.where("books.title ILIKE 'roman%' OR authors.name ILIKE 'pushkin%'")
.order("books.id DESC, authors.id DESC").limit(20).group("books.id, authors.id")
I got something like:
id | title | ...
123 | Roman1 | // this book has only 1 author
55 | roman2 |
55 | roman2 | // this one hase 2 authors
177 | Roman5 | ...
etc.
How can I merge those rows by id in sql query (btw, Postgres 9.1)?
The problem is not the order part, but the group by part. If you include the author, it means you make difference between the book and the author too.
I recommend you to omitt the author.id, and order the list from code, and not is SQL.