I am having four table i need to join all the four table in my rails model How can i do it
My Join sample schema is
select * from
(
select id,name from table1
)a
left join
(
select * from table2
)b
on a.id=b.user_id
left join
(
select * from table3
)c
on a.id=b.ord_id
left join
(
select * from table4
)d
on a.id=d.other_id
One of the best features of rails is that you don't have to worry much about writing these types of database setups. I think you would be very well served by going through the intro to ActiveRecord:
http://guides.rubyonrails.org/active_record_basics.html
ActiveRecord abstracts the SQL up one layer, so you're (in theory) not writing any database-specific code. It also allows you to conceptualize your database schema at a higher level, rather than simply doing left join, inner join, etc. See here for more info on the various associations:
http://guides.rubyonrails.org/association_basics.html
Related
I'm really struggling at the moment trying to work out how to join multiple tables without duplicating data.
At the moment I have 8 tables that I was wanted to get various information from per member of staff like the below:
SDQ score, Goal scores, CHI score, number of appointments, number of dna appointments
The tables and field I can see to join are as follows
tblSDQ - Assessed_By_Staff_ID
tblGoals - Recorded_By_Staff_ID
tblCHI - Recorded_By_Staff_ID
tblReferral - Staff_ID
tblStaff - Staff_ID
tblDiaryAppointment - needs to connect to tblDiaryAppointmentClinician using Clinician_Invitee_Staff_ID
I hope someone can help or advice. I just don't know if it's even possible to join all these tables using the same field, or if its possible to join them but then return a number of entries but then just count others?
Syntax depends on a rdbms you are using.
You could use join with specified join fields from both tables:
select bla-bla
from table1
join table2 on ( table1.fileld_name1 = table2.fileld_name2 )
https://dev.mysql.com/doc/refman/5.0/en/join.html
if you need outer join (to show nulls for optional tables data) you could use this:
join table2 on ( table1.fileld_name1 = table2.fileld_name2 or table2.field_name2 is null )
to join with couns you could use subqueries like this
join ( select field_name3, coint(*) as cnt from table3 goup by field_name3 ) AS table3_counts
...
where ( table3_counts.field_name3 = ... or table3_counts.field_name3 is null )
https://dev.mysql.com/doc/refman/5.0/en/from-clause-subqueries.html
PS: Joins are often slow. It's better to denormalize tables to eliminate joins and gain performance. Or do simple selects and join in backend code.
When I do includes it left joins the table I want to filter on, but when I add pluck that join disappears. Is there any way to mix pluck and left join without manually typing the sql for 'left join'
Here's my case:
Select u.id
From users u
Left join profiles p on u.id=p.id
Left join admin_profiles a on u.id=a.uid
Where 2 in (p.prop, a.prop, u.prop)
Doing this is just loading all the values:
Users.includes(:AdminProfiles, :Profiles).where(...).map{ |a| a[:id] }
But when I do pluck instead of map, it doesn't left join the profile tables.
Your problem is that you're using includes which doesn't really do a join, instead it fires a second query after the first one to query for the associations, in your case you want them both to be actually joined, so for that replace includes(:something) with joins(:something) and every thing should work fine.
Replying to your comment, i'm gonna quote few parts from the rails guide about active record query interface
From the section Solution to N + 1 queries problem
clients = Client.includes(:address).limit(10)
clients.each do |client|
puts client.address.postcode
end
The above code will execute just 2 queries, as opposed to 11 queries in the previous case:
SELECT * FROM clients LIMIT 10
SELECT addresses.* FROM addresses WHERE (addresses.client_id IN (1,2,3,4,5,6,7,8,9,10))
as you can see, two queries, no joins at all.
From the section Specifying Conditions on Eager Loaded Associations link
Even though Active Record lets you specify conditions on the eager loaded associations just like joins, the recommended way is to use joins instead.
Then an example:
Article.includes(:comments).where(comments: { visible: true })
This would generate a query which contains a LEFT OUTER JOIN whereas the joins method would generate one using the INNER JOIN function instead.
SELECT "articles"."id" AS t0_r0, ... "comments"."updated_at" AS t1_r5 FROM "articles" LEFT OUTER JOIN "comments" ON "comments"."article_id" = "articles"."id" WHERE (comments.visible = 1)
If there was no where condition, this would generate the normal set of two queries.
I have a nightly job that runs and computes some data in hive. It is partitioned by day.
Fields:
id bigint
rank bigint
Yesterday
output/dt=2013-10-31
Today
output/dt=2013-11-01
I am trying to figure out if there is a easy way to get incremental changes between today and yesterday
I was thinking about doing a left outer join but not sure what that looks like since its the same table
This is what it might looks like when there are different tables
SELECT * FROM a LEFT OUTER JOIN b
ON (a.id=b.id AND a.dt='2013-11-01' and b.dt='2-13-10-31' ) WHERE a.rank!=B.rank
But on the same table it is
SELECT * FROM a LEFT OUTER JOIN a
ON (a.id=a.id AND a.dt='2013-11-01' and a.dt='2-13-10-31' ) WHERE a.rank!=a.rank
Suggestions?
This would work
SELECT a.*
FROM A a LEFT OUTER JOIN A b ON a.id = b.id
WHERE a.dt='2013-11-01' AND b.dt='2013-10-31' AND <your-rank-conditions>;
Efficiently, this would span 1 MapReduce job only.
So I figured it out... Using Subqueries and Joins
select * from (select * from table where dt='2013-11-01') a
FULL OUTER JOIN
(select * from table where dt='2013-10-31') b
on (a.id=b.id)
where a.rank!=b.rank or a.rank is null or b.rank is null
The above will give you the diff..
You can take the diff and figure out what you need to ADD/UPDATE/REMOVE
UPDATE If a.rank!=null and b.rank!=null i.e rank changed
DELETE IF a.rank=null and b.rank!=null i.e the user is no longer ranked
ADD if a.rank!=null and b.rank=null i.e this is a new user
Is it not possible to perform a left join in Rhomobile?
I have models PriceGroups, PriceLookup which have a 1-many relationship (ie. each PriceGroup and have many PriceLookup records).
I need to do a simple SQL Left Join so I have the required information from the PriceGroups Table
SELECT * FROM PriceLookup
LEFT JOIN PriceGroups ON PriceLookup.price_group_code=PriceGroups.code
I have added this to the price_lookup model:
belongs_to :price_group_code, 'PriceGroups'
The following is what I have tried in Rhomobile
PriceLookup.find_by_sql("SELECT *
FROM PriceLookup
LEFT JOIN PriceGroups on PriceLookup.price_group_code=PriceGroups.code")
But I get error:
Error: could not prepare statement: 1; Message: no such table: PriceGroups
I know I can do two selects and join them myself but this is a very crap way of doing it
You need to create the RhoMobile model as FixedSchema, not using the default PropertyBags.
Otherwise you don't have a real table in SQLite but you're using the special objectValues table that is implementing a Key-Value store:
http://docs.rhomobile.com/rhodes/rhom#fixed-schema
Example:
dbPT = ::Rho::RHO.get_src_db('PriceLookup')
sql = "SELECT * FROM PriceLookup LEFT JOIN PriceGroups ON PriceLookup.price_group_code=PriceGroups.code"
lines = dbPT.execute_sql(sql)
This could happen if the table PriceGroups hasn't been initialized (created) yet. Tables are created when the model class is loaded, if they don't exist.
For your case, simply call the model class, this will load it and create the table if necessary.
PriceGroups; #Only for create the table
PriceLookup.find_by_sql("SELECT * FROM PriceLookup LEFT JOIN PriceGroups on PriceLookup.price_group_code=PriceGroups.code")
I need to generate such SQL using Propel build criteria:
"SELECT *
FROM `table1`
LEFT JOIN table2 ON ( table1.OBJECT_ID = table2.ID )
LEFT JOIN table3 ON ( table1.OBJECT_ID = table3.ID )
LEFT JOIN table4 ON ( table4.USER_ID = table2.ID
OR table4.USER_ID = table3.AUTHOR_ID )"
Is it possible to make join with or condition? Or maybe some other ways?
Propel 1.5
Table1Query::create()
->leftJoinTable2()
->leftJoinTable3()
->useTable2Query()
->leftJoinTable4()
->endUse()
->condition('cond1', Table4::USER_ID . ' = ' . Table2::ID)
->condition('cond2', Table4::USER_ID . ' = ' . Table3::AUTHOR_ID)
->combine(array('cond1', 'cond2'), Criteria::LOGICAL_OR, 'onClause')
->setJoinCondition('Table4', 'onClause')
->find();
useTable2Query() is necessary because your information seems to imply that Table4 is related to Table2 and not to Table1, and so joining Table4 directly to Table1 will result in a series of fatal Propel errors. The "use" functionality bridges that relationship.
The first two joins (table2, table3) are easy, if I recall correctly. Just make table1.OBJECT_ID non-required in your schema, and the left join will be used automatically.
Not immediately sure about the OR join. If you get stuck, one way to do it is to use the above in a raw query, and then "hydrate" objects from the resultset. Another way (very good for complex queries that are a pain to express in an ORM) is to create a database view for the above, and then add a new table in your schema for the view. It's cheating a bit for sure, but for some really complex master-detail things I did in a large symfony project, it was great - and it made query debugging really easy as well.