Duplicate entity on join request with Query Builder - join

I'm using the Laravel's query builder with this syntax :
$article = DB::table('users')->join('articles', 'articles.id', '=', 'users.id')->where('article_id', $id)->first();
You can see that both articles and users table have an id column.
Then in my view I use the query result, and I only get one id whereas I need both.
Is there any way to get them ?
I know I could use :
->select('articles.id as myFirstId', 'users.id as mySecondId', 'users.name', ...)
But there are many columns in this request, and if I can avoid it I'd prefer.
Thanks
Raphaƫl N.

You can select all fields from the table with higher number of fields with * FROM table and then pick one by one from the other table, like this:
$article = DB::table('users')
->join('articles', 'articles.id', '=', 'users.id')
->where('article_id', $id)
->select('articles.*', 'users.id as userId', 'users.name') // Add rest of `users` fields
->first();

Related

Retrive records which are not referenced in other table, ActiveRecord query

There are 2 tables : User and Teacher. Teacher.user_id is from User. So, how do I find in a single query, all the users who are not in teachers.
I meant something along the lines :
User.not_in(Teacher.all)
You can use where.not query from ActiveRecord try something like below:
User.where.not(id: Teacher.pluck(:user_id).reject {|x| x.nil?})
Note: used reject method, in case you have nil values in some records.
The other users seem to have neglected the rails 3 tag (since removed based on the approved answer. My answer left for posterity) : Please try this
User.where("id NOT IN (?)",Teacher.pluck(:user_id).join(","))
This will become SELECT * FROM users WHERE id NOT IN (....) (two queries one to get the user_id from teachers and another to get the user(s) not in that list) and may fail based on the size of teacher table.
Other option is an arel table:
users = User.arel_table
User.where(users[:id].not_in(Teacher.select(:user_id).where("user_id IS NOT NULL")))
This should produce a single query similar to
SELECT * FROM users
WHERE id NOT IN ( SELECT user_id FROM teachers WHERE user_id IS NOT NULL)
(one query better performance) * syntax was not fully tested
Another single query option might be
User.joins("LEFT OUTER JOIN teachers ON teachers.user_id = users.id").
where("teachers.user_id IS NULL")
I think you should be able to do something like this
User.where.not(id: Teacher.ids)

Access 'Not Equal To' Join

I have two tables, neither with a primary id. The same combination of fields uniquely identifies the records in each and makes the records between the two tables relate-able (I think).
I need a query to combine all the records from one table and only the records from the second not already included from the first table. How do I do this using 'not equal to' joins on multiple fields? My results so far only give me the records of the first table, or no records at all.
Try the following:
SELECT ECDSlides.[Supplier Code], ECDSlides.[Supplier Name], ECDSlides.Commodity
FROM ECDSlides LEFT JOIN (ECDSlides.Commodity = [Mit Task Details2].Commodity) AND (ECDSlides.[Supplier Code] = [Mit Task Details2].[Supplier Code])
WHERE [Mit Task Details2].Commodity Is Null;
This might be what you are looking for
SELECT fieldA,fieldB FROM tableA
UNION
SELECT fieldA,fieldB FROM tableB
Union should remove automatically. 'Union All' would not.
If, for some reason, you get perfect duplicates and they are not removed, you could try this :
SELECT DISTINCT * FROM (
SELECT fieldA,fieldB FROM tableA
UNION
SELECT fieldA,fieldB FROM tableB
) AS subquery

SQLite select distinct join query how to

I have a sqlite database that I'm trying to build a query. The table column I need to retrieve is iEDLID from the table below :
Right now all I have to go on is a known iEventID from the table below :
And the the nClientLocationID from the table below.
So the requirements are I need to get current iEDLID to write, lookup from tblEventDateLocations for dEventDate and the tblLocation.nClientLocationID based on the tblLocations.iLocationID I already have and event selected on this screen.
So I would need a query that does a "SELECT DISTINCT table EventDateLocations.iEDLID FROM tblEventDateLocations ...."
So basically from another query I have the iEventID I need, and I have the event ID i need but where the dEventDate=(select date('now')) I need to retrieve the iEventDateID from table EventDates.iEventDateID to use on the table EventDateLocations
this is the point where I'm trying to wrap my head around the joins for this query and the syntax...
It seems like you want this:
select distinct edl.iEDLDID
from
tblEventDateLocations edl
join tblEventDates ed on edl.EventDateId = ed.EventDateId
where
ed.EventId = ?
and ed.dEventDate = date('now')
and edl.nClientLocationID = ?
where the ? of course represent the known event ID and location ID parameters.
Since nClientLocationId appears on table tblEventDateLocations you do not need to join table tblLocations unless you want to filter out results whose location ID does not appear in that table.

Convert SQL to ActiveRecord

What is the most appropriate way to convert the following SQL to an ActiveRecord query?
select count(*) from products where id in (
select product_id from store_locations
where store_id in (
select id from stores where store_definition_id = 1
)
)
This uses joins instead of sub queries, but if you're associations are setup correctly should work. I may have messed up the syntax a little bit, but I think it's right.
Product.joins(store_locations: :stores).where(stores: {store_definition_id: 1}).count
EDIT
The above is going to return more rows than you want as it each store_locations row will be returned with the product. Not good. So perhaps:
Product.where(id: StoreLocation.joins(:store).where(store: {store_definition_id: 1}).pluck(:product_id)).count

Laravel eloquent selecting most recent row from joined table

I have two tables, Project and Projectnote
There is a one to many relationship between project and projectnote.
I want to be able to list my projects and select the most recent projectnotes based on the created_at date.
Is this possible to do in Eloquent, I can't figure it out.
Thanks for any help!
Edit: so far I have a basic query (below) that joins the two tables. However, this only selects projects where a note exists and I get multiple rows where there are several notes per project.
$projects = Project::join('projectnotes', 'projectnotes.project_id', '=', 'projects.id')
->select(array('projects.*', 'projectnotes.note as note'))
->get();
You can join the table on the latest value:
->join('t1', function($join) {
$join->on('t1.t2_id', '=', 't2.id')
->on('t1.id', '=', DB::raw("(select max(id) from t1 WHERE t1.t2_id = t2.id)"));
If you also want to join where t1 does not have a value, use a leftJoin. In your case this would look like this:
$projects = Project::leftJoin('projectnotes', function($join) {
$join->on('projectnotes.project_id', '=', 'projects.id')
->on('projectnotes.id', '=', DB::raw("(SELECT max(id) from projectnotes WHERE projectnotes.project_id = projects.id)"));
})
->select(array('projects.*', 'projectnotes.note as note'))
I would suggest you try to order by id in that specific scenario; the below is my suggested solution for you based on your code:
$projects = Project::join('projectnotes', 'projectnotes.project_id', '=', 'projects.id')
->select(array('projects.*', 'projectnotes.note as note'))
->orderBy('projectnotes.id')
->latest('projectnotes.id')
->get()->unique();
The code above works on Laravel 5.6; your can try it out.
In your project model, make the notes relationship function look something like:
public function notes() {
return $this->hasMany('Note');
}
Then you can get the most recent Note of the Project with primary key 1 by chaining orderBy and first:
Project::find(1)->notes()->orderBy('created_at', 'desc')->first();
Also, is your note table called 'Note' or 'Notes'? (Keeping with Laravel style, it should be named singular as I have it in this code)

Resources