activerecord class from custom sql query - ruby

Is it possible to create an activerecord class from a custom sql query or view ?
It doesn't need to be editable.
example:
class c
select a.*, b.* from a, b where a.code = b.code
end
This example is a join where all the fields from both tables are resent, the one to one joins in activerecord only present fields from one table, the others are accessible through a.bs.fieldname.
I would like them aal to be fields on the same level, thus in one class.
so that a.code, a.name and b.code, b.extra can be accessed as c.code, c.name, c.extra

ActiveRecord will works with your views as with tables. So, firstly create custom view for your things
CREATE VIEW some_things AS (select a.*, b.* from a, b where a.code = b.code)
And then make ActiveRecord based class for accessing them (app/models/some_thing.rb)
class SomeThing < ActiveRecord::Base
end
You can access to your things as like as any other AR objects
p SomeThing.where(code: 'xxx-yyy').order(:name).limit(10).all

Related

Laravel 5.4 Eloquent multiple table query

Hi I want to form a query in laravel 5.4 eloquent for the following SQL:
select A.*, concat(B.firstname, ' ', B.lastname) as clientname, C.category as category from payments A, clients B, categories C where A.client_id = B.id and A.category_id = C.id
All the foreign keys are properly given and the models are also properly created.
My aim is to get all the master record name like category, client name, etc to come in the child table record set directly.
You can try this:
DB::table('payments')
->select('payments.*',DB::raw('CONCAT(clients.firstname," ",clients.lastname) as clientname'),categories.category)
->join('clients','clients.id','=','payments.client_id')
->join('categories','categories.id','=','payments.category_id')
->get();
Hope this help for you !!!
Paste your row query in DB::row() and print data like following
$data= DB::row("select A.*, concat(B.firstname, ' ', B.lastname) as clientname, C.category as category from payments A, clients B, categories C where A.client_id = B.id and A.category_id = C.id")->get();
dd($data);
if your query is right and properly managed relation than its retrieve data
If you already made Models than Why you don't use ORM?
Use Models,
payment::leftJoin('clients ','payments.client_id','=','clients.id')
->leftJoin('categories ','payments.category_id ','=','categories .id')->select(['payment.*','categories.category',DB::raw("CONCAT(clients.firstname,' ',clients.lastname) as clientname")])->get();

Left Join with Sub Query in grails?

How do i write below query in Grails either using criteria query or executeQuery?
select * from table1 as t1 left Join(select * from table2 where id=2)as t2 On t2.table1=t1.id ;
Unlike SQL, in which you query tables, GORM/Hibernate queries query domain classes. Yes, it boils down to tables, but from the Criteria, WHERE, and HQL point-of-view, it's domain classes. Which is why, as Koloritnij pointed out, knowledge of the domain model is necessary for writing the query.
SQL vs GORM
One difference in how SQL and GORM perform joins is that SQL joins are created on-the-fly, in the SQL itself. Whereas GORM joins are predetermined by the domain class associations. This means that in HQL you cannot join to a sub-query. You can read more about such differences here.
An example
That being said, using your example SQL I made an assumption about your domain model:
class DomainA {
}
class DomainB {
DomainA a
}
In the domain model above, DomainB (table2) has a uni-directional many-to-one association with DomainA (table1). An HQL similar to your SQL is as follows:
def hql = 'SELECT a, b FROM DomainB AS b RIGHT OUTER JOIN b.a AS a WHERE b.id = :id'
The HQL can be executed like this:
def result = DomainB.executeQuery(hql, [id: 2])
Here you go (if you have Domain Classes with foreign key):
def query
query = sessionFactory.getCurrentSession().createCriteria(table2.class)
query = query.createAlias("table1", "table1Alias", CriteriaSpecification.LEFT_JOIN, Restrictions.in( 'table1Alias.id', 'table2.id'))
Restrictions.eq( "id", 2)
If not, you have to use raw SQL:
def dataSource
Sql sql = new Sql(dataSource)
sql.exequteQuery("""....""")

How to get entities in a many-to-many relationship that do NOT have a corresponding linked entity with DQL and Doctrine?

I have a standard many-to-many relationship set up. Entity A can have many of Entity B, and vice versa.
I'm trying to get a list of all Entity A that do NOT have any corresponding Entity B. In SQL, I'd run a query like this:
SELECT a.* FROM entity_a a LEFT JOIN a_b r ON r.AID = a.id WHERE r.BID IS NULL
In this query, a_b is the linking table.
I'm trying to write a DQL statement (or use some other method) to get the same result, but the following does not work:
SELECT s FROM VendorMyBundle:EntityA s LEFT JOIN VendorMyOtherBundle:EntityB u WHERE u IS NULL
How can I achieve what I'm trying to do?
First, I have to underline that usually you should JOIN on the property of the entity (i.e. s), e.g. instead of:
SELECT s FROM VendorMyBundle:EntityA s
LEFT JOIN VendorMyOtherBundle:EntityB u WHERE u IS NULL
you should have something like:
SELECT s FROM VendorMyBundle:EntityA s
LEFT JOIN s.mylistofb u WHERE u IS NULL
where I'm supposing that in entity A you have defined your relationship as:
class A{
// ...
/**
* #ManyToMany(targetEntity="Vendor\MyBundle\Entity\EntityB")
* #JoinTable(name="as_bs",
* joinColumns={#JoinColumn(name="a_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="b_id", referencedColumnName="id", unique=true)}
* )
**/
private $mylistofb;
This stated, if the query is not working yet, then try the following:
SELECT s FROM VendorMyBundle:EntityA s
WHERE SIZE(s.mylistofb) < 1
It is simplest than the previous and also comes from the official docs (i.e. see "phonenumbers example").

How do I perform a full join in ARel?

Assume I have two tables TableA and TableB with a many-to-many relationship through a joining table TableABJoin. I would like to use ARel 3 to generate a query that performs a full join of TableA and TableB.
The query I want to generate should be something along these lines:
SELECT a.id, b.code
FROM TableA as a, TableB as b
This results in a full join of tables A and B.
The closest I have been able to get, without writing an explicit sql string, is to hack an outer join:
part_a = TableA.arel_table
part_b = TableB.arel_table
query = part_a.join(part_b, Arel::Nodes::OuterJoin).on('1=1').project(part_a[:id], part_b[:code]).to_sql
This produces the following SQL:
SELECT "TableA"."id", "TableB"."code" FROM "TableA" LEFT OUTER JOIN "TableB" ON 1=1
If I exclude the .on component I end up with a trailing NULL:
SELECT "TableA"."id", "TableB"."code" FROM "TableA" LEFT OUTER JOIN "TableB" NULL
Is there a more reasonable way to generate a proper full join or at least generate the same result without hacking a left outer join in ARel?
Actually, is not possible to perform a full outer join (and a right outer join) with arel, which only supports Inner and Outer (LEFT OUTER) joins.
Because I didn't like this, I updated arel 3-0-stable (I'm working on a 3.2.13 rails application) so that it supports right and full outer joins too. Adding those was pretty straightforward even with undocumented code, it's quite easy so you should face no issue if you try it.
Here you can find my pull request: https://github.com/rails/arel/pull/202
And here you can find the updated repository with a branch: https://github.com/Fire-Dragon-DoL/arel/tree/3-0-right-full-outer-join
You can easily use this in a rails application by adding this to your Gemfile:
gem 'arel', '~> 3.0.3.4', github: 'Fire-Dragon-DoL/arel', branch: '3-0-right-full-outer-join'
Here you can see a syntax example:
class Cat < ActiveRecord::Base
has_many :cat_diseases
end
class Disease < ActiveRecord::Base
has_many :cat_diseases
end
class CatDisease < ActiveRecord::Base
belongs_to :cat
belongs_to :disease
def self.all_diseases_for_cat(cat)
cat_diseases = self.arel_table
diseases = Disease.arel_table
scoped
.joins(
cat_diseases.join(diseases, Arel::Nodes::RightOuterJoin)
.on(cat_diseases[:disease_id].eq(diseases[:id]))
.join_sources
)
.where(
cat_diseases[:cat_id].eq(cat.id)
.or(cat_diseases[:cat_id].eq(nil))
)
end
end
I write the join in SQL. Its clearer and works fine:
part_a = TableA.arel_table
part_b = TableB.arel_table
query = part_a.joins('LEFT OUTER JOIN "TableB"').other_scopes.to_sql

TSQL equivalent of Linq SelectMany

I would like the resultset that consists of the union of queries performed based on each row of an outer SELECT query. How do I do this?
As an example:
create table Person
(
Id int,
Age int
)
create table Movie
(
Id int,
Title varchar(500),
AgeRestriction int
)
I would like a resultset that shows me, for every person, which movies that person would be allowed to watch.
UPDATE: Ok, so as it turns out there is no "equivalent" of SelectMany in TSQL since the model is completely different, as the author of the correct answer has pointed out an inner join will do the job just fine.
Your question is pretty unclear but it sounds like you might want CROSS APPLY
Random Example
SELECT DISTINCT ca.* /*DISTINCT for UNION semantics*/
FROM master..spt_values v
CROSS APPLY (SELECT TOP 2 *
FROM sys.columns c
WHERE c.name > v.name
ORDER BY c.name) ca
Edit. Following clarification you just need a JOIN
SELECT P.Id,
M.Title
FROM Person P
JOIN Movie M
ON M.AgeRestriction <= P.Age

Resources