getting the count of another table values in existing query Rails - ruby-on-rails

Currently I am doing this to get data from my tables as
cameras = Camera.joins("left JOIN users on cameras.owner_id = users.id")
.joins("left JOIN vendor_models vm on cameras.model_id = vm.id")
.joins("left JOIN vendors v on vm.vendor_id = v.id")
.where(condition).order(sorting(col_for_order, order_for)).decorate
And this generates such query as
SELECT "cameras".* FROM "cameras" left JOIN users on cameras.owner_id = users.id left JOIN vendor_models vm on cameras.model_id = vm.id left JOIN vendors v on vm.vendor_id = v.id
I have an other table as camera_shares on which I have relation of camera's table as there is a camera_id which is present in camera_shares table as well, in each camera_shares there is an camera_id which tell us that the share is for which camera, I want to calculate the count of camera_shares, For example if there is a camera with id 12 and there are also 20 camera_shares with camera_id = 12 then I want to count the total of it. I want to do that in Rails query as I have shown above? How is that possible to do?

Seems rather straightforward. Suppose you want to find the number of camera_shares for #camera:
CameraShare.where(camera: #camera).count

Related

SQL Join issue with 3 tables and a subquery

Tables Involved:
account, user, service, accesshist
I want to include all records in the account table, and only the data from the other tables when it exists.
Count from account: 5064
rows returned from query below: 4915
select u.last_name, u.first_name, a.username, ll.mxlogin, si.servicename, a.islockedout
from account a
join service si on a.serviceid = si.serviceid
left outer join user u on u.loginid = a.username
left outer join(select max(loginattemptdate) as MxLogin, usernameattempted from accesshist where isloginsuccessful = 1
group by usernameattempted) ll
on a.username = ll.usernameattempted
where a.isenabled = 1
order by ll.mxlogin, u.last_name
I've narrowed it down that the subquery join is the part causing the number of rows to be reduced, but I am unsure how to correct it. Any insight is greatly appreciated!
Have you tried changing the first join to a left outer join?
select u.last_name, u.first_name, a.username, ll.mxlogin, si.servicename, a.islockedout
from account a
left outer join service si on a.serviceid = si.serviceid

Unusual Joins SQL

I am having to convert code written by a former employee to work in a new database. In doing so I came across some joins I have never seen and do not fully understand how they work or if there is a need for them to be done in this fashion.
The joins look like this:
From Table A
Join(Table B
Join Table C
on B.Field1 = C.Field1)
On A.Field1 = B.Field1
Does this code function differently from something like this:
From Table A
Join Table B
On A.Field1 = B.Field1
Join Table C
On B.Field1 = C.Field1
If there is a difference please explain the purpose of the first set of code.
All of this is done in SQL Server 2012. Thanks in advance for any help you can provide.
I could create a temp table and then join that. But why use up the cycles\RAM on additional storage and indexes if I can just do it on the fly?
I ran across this scenario today in SSRS - a user wanted to see all the Individuals granted access through an AD group. The user was using a cursor and some temp tables to get the users out of AD and then joining the user to each SSRS object (Folders, reports, linked reports) associated with the AD group. I simplified the whole thing with Cross Apply and a sub query.
GroupMembers table
GroupName
UserID
UserName
AccountType
AccountTypeDesc
SSRSOjbects_Permissions table
Path
PathType
RoleName
RoleDesc
Name (AD group name)
The query needs to return each individual in an AD group associated with each report. Basically a Cartesian product of users to reports within a subset of data. The easiest way to do this looks like this:
select
G.GroupName, G.UserID, G.Name, G.AccountType, G.AccountTypeDesc,
[Path], PathType, RoleName, RoleDesc
from
GroupMembers G
cross apply
(select
[Path], PathType, RoleName, RoleDesc
from
SSRSOjbects_Permissions
where
Name = G.GroupName) S;
You could achieve this with a temp table and some outer joins, but why waste system resources?
I saw this kind of joins - it's MS Access style for handling multi-table joins. In MS Access you need to nest each subsequent join statement into its level brackets. So, for example this T-SQL join:
SELECT a.columna, b.columnb, c.columnc
FROM tablea AS a
LEFT JOIN tableb AS b ON a.id = b.id
LEFT JOIN tablec AS c ON a.id = c.id
you should convert to this:
SELECT a.columna, b.columnb, c.columnc
FROM ((tablea AS a) LEFT JOIN tableb AS b ON a.id = b.id) LEFT JOIN tablec AS c ON a.id = c.id
So, yes, I believe you are right in your assumption

joins on multiple related tables

I have 3 table customer (customerid,name), customerbooking(bookingid,customerid), transact(transacted,bookingid,typeoftransaction)
I want to fetch the name of the ‘customer name’ who has the maximum typeoftransact=’current’. Customer table is linked to customerbooking via customerid, and customerbooking is linked to transact via bookingid. Using join I am able to get the individual records, but unable to get the Max value
Please try this to meet your scenerio
SELECT
C.Name
, Count(BookingID)
FROM Customer C
INNER JOIN customerbooking CB ON CB.CustomerID = C.customerId
INNER JOIN transact T ON T.bookingid = CB.BookingId
WHERE T.Typeoftransaction='current'
GROUP BY C.Name
Hope this helps

Number of joins in select query

I have a business table and in that we have 50 foreign key columns which refers other master data tables.
to fetch all the data my query has to join all the 50 reference tables like
select ct.id , ct.name , ct.description , st.value , pr.value , sv.value , ....
from
core_table ct
left outer join domain_value st on ct.status_fk = st.id
left outer join domain_value pr on ct.priority_fk = pr.id
left outer join domain_value svon ct.severity_fk = sv.id
.......
.......
so like this i need to make 50 left outer joins.
is this right to do 50 left outer joins like this or do we have any other optimized way to achieve this ?
Is too many Left Joins a code smell?
It's a perfectly legitimate solution for some designs.

Using RoR with a legacy table that uses E-A-V

I'm needing to connect to a legacy database and pull a subset of data from a table that uses the entity-attribute-value model to store a contact's information. The table looks like the following:
subscriberid fieldid data
1 2 Jack
1 3 Sparrow
2 2 Dan
2 3 Smith
where fieldid is a foreign key to a fields table that lists custom fields a given customer can have (e.g. first name, last name, phone). The SQL involved is rather hairy as I have to join the table to itself for every field I want back (currently I need 6 fields) as well as joining to a master contact list that's based on the current user.
The SQL is something like this:
select t0.data as FirstName, t1.data as LastName, t2.data as SmsOnly
from subscribers_data t0 inner join subscribers_data t1
on t0.subscriberid = t1.subscriberid
inner join subscribers_data t2
on t2.subscriberid = t1.subscriberid
inner join list_subscribers ls
on (t0.subscriberid = ls.subscriberid and t1.subscriberid = ls.subscriberid)
inner join lists l
on ls.listid = l.listid
where l.name = 'My Contacts'
and t0.fieldid = 2
and t1.fieldid = 3;
How should I go about handling this with my RoR application? I would like to abstracat this away and still be able to use the normal "dot notation" for pulling the attributes out. Luckily the data is read-only for the foreseeable future.
This is exactly what #find_by_sql was designed for. I would reimplement #find to do what you need to do, something like this:
class Contact < ActiveRecord::Base
set_table_table "subscribers_data"
def self.find(options={})
find_by_sql <<EOS
select t0.data as FirstName, t1.data as LastName, t2.data as SmsOnly
from subscribers_data t0 inner join subscribers_data t1
on t0.subscriberid = t1.subscriberid
inner join subscribers_data t2
on t2.subscriberid = t1.subscriberid
inner join list_subscribers ls
on (t0.subscriberid = ls.subscriberid and t1.subscriberid = ls.subscriberid)
inner join lists l
on ls.listid = l.listid
where l.name = 'My Contacts'
and t0.fieldid = 2
and t1.fieldid = 3;
EOS
end
end
The Contact instances will have #FirstName and #LastName as attributes. You could rename them as AR expects too, such that #first_name and #last_name would work. Simply change the AS clauses of your SELECT.
I am not sure it is totally germane to your question, but you might want to take a look at MagicModel. It can generate models for you based on a legacy database. Might lower the amount of work you need to do.

Resources