Convert SQL query to Rails ActiveRecord query - mysql

I have an sql query with multiple left joins that works fine:
query = <<-eos
select date(t.completed_at) completed_date, s.id district, assignee_id, u.first_name, u.last_name, count(t.id) completed_tasks
from tasks t
left join tickets k on k.id = t.ticket_id
left join installations i on i.id = k.installation_id
left join administrative_areas a on i.ward_id = a.id
left join service_areas s on s.id = a.service_district_id
left join users u on u.id = t.assignee_id
where 1 = 1
and s.id = '#{district_id}'
and t.status = '#{status}'
and t.kind = 1
and t.completed_at >= '#{days_ago.days.ago.beginning_of_day.to_s(:db)}'
and t.completed_at <= '#{days_until.days.ago.beginning_of_day.to_s(:db)}'
group by date(t.completed_at), s.id, s.name, u.first_name, u.last_name, t.assignee_id
eos
I got this value after mapping: [{:completed_date=>"2015-07-11", :district=>"1339", :assignee_id=>"215371", :assignee_name=>nil, :first_name=>"John_9", :last_name=>"Ant", :completed_tasks=>"1"}] for the sql query.
But I want to stop using the sql query and switch to ActiveRecord query and I have it converted to ActiveRecord like this:
Task.joins("LEFT JOIN tickets k ON k.id = tasks.ticket_id").
joins("LEFT JOIN installations i ON i.id = k.installation_id").
joins("LEFT JOIN administrative_areas a ON i.ward_id = a.id").
joins("LEFT JOIN service_areas s ON s.id = a.service_district_id").
joins("LEFT JOIN users u ON u.id = tasks.assignee_id").
where(["s.id = ? and tasks.status = ? and tasks.kind = ? and tasks.completed_at >= ? and tasks.completed_at <= ?", 26, "#{status}", 1, "#{days_ago.days.ago.beginning_of_day.to_s(:db)}", "#{days_until.days.ago.beginning_of_day.to_s(:db)}"]).
select('date(tasks.completed_at) as completed_date, s.id as district, assignee_id, u.first_name, u.last_name, count(tasks.id) as completed_tasks').
group("date(tasks.completed_at), s.id, s.name, u.first_name, u.last_name, tasks.assignee_id")
But the problem I have here is trying to do a select from multiple columns in different tables, the only value that the ActiveRecord query returns belong to the task table alone. I don't know what am doing wrong, maybe it's the left joins or the select
[#<Task status: 1, assignee_id: 215356, kind: 1>]
Please, how do I convert the above sql query to ActiveRecord query and get the same result?

You can use Scuttle.io the first result is always terrible, but try to configure associations in second tab. And please try to avoid constructions like this:
where("params.id = #{param[:id]}")
it is unsecured (sql injection)!

Related

SSRS: Parameter not filtering MySQL query

I have a Date/Time parameter to my report:
But when I run my query, I get no results:
SELECT HD_QUEUE.NAME as qname, HD_TICKET.ID, HD_TICKET.CREATED, HD_TICKET.TIME_CLOSED, CUSTOMER.FULL_NAME as custfullname,
HD_STATUS.NAME as statname, HD_TICKET.TITLE, left(ASSIGNEE.FULL_NAME, 40) as assignee,
HD_PRIORITY.NAME as pname, HD_CATEGORY.NAME as catname
FROM HD_TICKET
INNER JOIN HD_QUEUE
ON HD_TICKET.HD_QUEUE_ID = HD_QUEUE.ID
INNER JOIN USER CUSTOMER
ON HD_TICKET.SUBMITTER_ID=CUSTOMER.ID
INNER JOIN USER ASSIGNEE
ON HD_TICKET.OWNER_ID=ASSIGNEE.ID
INNER JOIN HD_STATUS
ON (HD_TICKET.HD_STATUS_ID=HD_STATUS.ID)
AND (HD_TICKET.HD_QUEUE_ID=HD_STATUS.HD_QUEUE_ID)
INNER JOIN HD_PRIORITY
ON HD_TICKET.HD_PRIORITY_ID = HD_PRIORITY.ID
and HD_TICKET.HD_QUEUE_ID = HD_PRIORITY.HD_QUEUE_ID
INNER JOIN HD_CATEGORY
ON HD_TICKET.HD_CATEGORY_ID = HD_CATEGORY.ID
and HD_TICKET.HD_QUEUE_ID = HD_CATEGORY.HD_QUEUE_ID
left join ASSET on ASSET.ID = HD_TICKET.ASSET_ID
left join ASSET_DATA_6 on ASSET.ASSET_DATA_ID = ASSET_DATA_6.ID
WHERE (HD_STATUS.NAME = 'Closed'
AND HD_TICKET.TIME_CLOSED < #date_param);
What am I doing wrong?
MySQL does not allow named parameters. Use '?' instead of '#date_param' in the query.
WHERE (HD_STATUS.NAME = 'Closed'
AND HD_TICKET.TIME_CLOSED < ?;
Then check the Dataset Properties and make sure the '?' is associated with the value of your parameter:

Query inside NOT IN statement Doctrine

I found this sentence in the code:
$dql
= <<<DQL
SELECT u FROM AppBundle:User u
JOIN u.Roles r
JOIN u.team t
WHERE u.id NOT IN (
SELECT user.id
FROM GameBundle:Goal g
JOIN g.user user
WHERE
g.objective = :objective
)
AND
r.profile = :sales_profile
AND
r.company = :company
AND
u.onlyStatus NOT IN (:status)
DQL;
I don't know how to works that query inside NOT IN sentence, help me please.
I need to know:
What return the query inside of NOT IN, (data types, so on...)
How to works a query inside of NOT IN (is posible ?)
SELECT u FROM AppBundle:User u
JOIN u.Roles r
JOIN u.team t
WHERE u.id NOT IN (
SELECT user.id
FROM GameBundle:Goal g
JOIN g.user user
WHERE
g.objective = :objective
)
this means take all the users that don't currently have 'objective' in the 'Goal' table.
Is this what you needed ?

Mysql multiple tables left join last table

I have checked several threads on here and cannot find the answer to my question....
I am trying to do a mysql query with multiple tables and left join the last table. It does not like the left join and gives me no results when I include it. Any help is greatly appreciated :)
(I am using Joomla)
query = "SELECT DISTINCT u.id as uid, CONCAT(u.first_name,' ',u.last_name) as name1,
u.grad as grad, u.opt_out as opt_out
FROM #__bl_teams as t, #__bl_regions as r, #__users as u
LEFT JOIN #__bl_paid as pd ON pd.u_id = u.id
WHERE u.team_id = t.id AND u.team_id != '' AND u.s_id = $sid
AND ((t.id = $tid)OR($tid=0)) AND (t.id IN ($teamsfull))
AND ( (t.id IN(".$tc_teams."))OR(".$tc_id." = 0))
AND ((r.id = ".$mid.")OR(".$mid." = 0))
AND ((r.s_id = ".$sid.")OR(".$mid." = 0))
AND ( (FIND_IN_SET(t.id,r.teams) )OR(".$mid." = 0) )
AND u.id NOT IN($paidrows) AND u.id NOT IN ($rsrows) GROUP BY u.id";
$db->setQuery($query, $pageNav->limitstart, $pageNav->limit);
$rows50 = $db->loadObjectList();
You are mixing old-style joins and new style joins. That is your problem. The table aliases aren't recognized throughout the from statement, the way you expect them to be. Buried in the documentation is this warning:
However, the precedence of the comma operator is less than of INNER
JOIN, CROSS JOIN, LEFT JOIN, and so on. If you mix comma joins with
the other join types when there is a join condition, an error of the
form Unknown column 'col_name' in 'on clause' may occur. Information
about dealing with this problem is given later in this section.
Simple rule: Never use commas in the from clause.
So, rewrite your query using explicit joins and that will fix the problem.
I don't know the ctual tables, but this query is too long and will have unexpected results results. Anyways, Left join the other tables too.
query = "SELECT DISTINCT u.id as uid, CONCAT(u.first_name,' ',u.last_name) as name1,
u.grad as grad, u.opt_out as opt_out
FROM #__users as u
LEFT JOIN #__bl_paid as pd ON pd.u_id = u.id
LEFT JOIN #__bl_teams as t ON t.u_id = u.id
LEFT JOIN #__bl_regions as r ON r.u_id = u.id
WHERE u.team_id != ''
AND u.s_id = $sid
AND ((t.id = $tid)
OR($tid=0))
AND (t.id IN ($teamsfull))
AND ( (t.id IN(".$tc_teams."))
OR(".$tc_id." = 0))
AND ((r.id = ".$mid.")
OR(".$mid." = 0))
AND ((r.s_id = ".$sid.")
OR(".$mid." = 0))
AND ( (FIND_IN_SET(t.id,r.teams) )
OR(".$mid." = 0) )
AND u.id NOT IN($paidrows)
AND u.id NOT IN ($rsrows)
GROUP BY u.id";

Count number of occurrences based on user id

I'm very new to SQL/MySQL and Stackoverflow for that matter, and I'm trying to create a query through iReport (though I don't have to use iReport) for SugarCRM CE. What I need is to create a report that displays the number of "Referrals", "Voicemails", "Emails", and "Call_ins" that are linked to a specific "user" (employee). The query I currently have set up works; however it is running through the data multiple times generating a report that is 200+ pages. This is the code that I am currently using:
SELECT
( SELECT COUNT(*) FROM `leads` INNER JOIN `leads_cstm` ON `leads`.`id` = `leads_cstm`.`id_c` WHERE (leadtype_c = 'Referral' AND users.`id` = leads.`assigned_user_id`) ),
( SELECT COUNT(*) FROM `leads` INNER JOIN `leads_cstm` ON `leads`.`id` = `leads_cstm`.`id_c` WHERE (leadtype_c = 'VM' AND users.`id` = leads.`assigned_user_id`) ),
( SELECT COUNT(*) FROM `leads` INNER JOIN `leads_cstm` ON `leads`.`id` = `leads_cstm`.`id_c` WHERE (leadtype_c = 'Email' AND users.`id` = leads.`assigned_user_id`) ),
users.`first_name`,users.`last_name`
FROM
`users` users,
`leads` leads
I would appreciate any guidance!
You want to use conditional summation. The following uses MySQL syntax:
SELECT sum(leadtype_c = 'Referral') as Referrals,
sum(leadtype_c = 'VM') as VMs,
sum(leadtype_c = 'Email') as Emails,
users.`first_name`, users.`last_name`
FROM users join
`leads`
on users.`id` = leads.`assigned_user_id` INNER JOIN
`leads_cstm`
ON `leads`.`id` = `leads_cstm`.`id_c`
group by users.id;
You can use COUNT with CASE for this:
SELECT u.first_name,
u.last_name,
count(case when leadtype_c = 'Referral' then 1 end),
count(case when leadtype_c = 'VM' then 1 end),
count(case when leadtype_c = 'Email' then 1 end)
FROM users u
JOIN leads l ON u.id = l.assigned_user_id
JOIN leads_cstm lc ON l.id = lc.id_c
GROUP BY u.id
To match your exact results, you should probably use an OUTER JOIN instead, but this gives you the idea.
A Visual Explanation of SQL Joins

MySQL / PHP - 2 different arguments for 1 table

I have the following SQL:
$queryString = "
SELECT
iR.lastModified,
d.*,
c2.title as stakeholderTitle,
u.username as authorUsername,
c.title as authorContactName,
GROUP_CONCAT(iR.stakeholderRef) AS participants
FROM
informationRelationships iR,
contacts c2
INNER JOIN
debriefs d ON
d.id = iR.linkId
LEFT JOIN
users u ON
u.id = iR.author
LEFT JOIN
contacts c ON
c.ref = u.contactId
LEFT JOIN
debriefs d2 ON
d2.stakeholder = c2.ref
WHERE
(
iR.clientRef = '$clientRef' OR
iR.contactRef = '$contactRef'
)
AND
iR.projectRef = '$projectRef' AND
iR.type = 'Debrief'
GROUP BY
iR.linkId
ORDER BY
d.dateOfEngagement
";
notice how I require 2 different bits of data for the the contacts table.
So at one point, I need to match
c.ref = u.contactId
This will return one bit of information
but I also need a completely different grouping:
d2.stakeholder = c2.ref
Problem is that the title is the column i'm interested in for both:
c2.title as stakeholderTitle,
...
c.title as authorContactName
How do I go about doing this?
My current try is returning:
Error: Unknown column 'iR.linkId' in 'on clause'
I'm not sure I really understand what is happening here:
how to join two tables on common attributes in mysql and php?
EDIT::::---ANSWERED--zerkms
$queryString = "
SELECT
iR.lastModified,
d.*,
c2.title as stakeholderTitle,
u.username as authorUsername,
c.title as authorContactName,
GROUP_CONCAT(iR.stakeholderRef) AS participants
FROM
informationRelationships iR
INNER JOIN
debriefs d ON
d.id = iR.linkId
INNER JOIN
contacts c2 ON
d.stakeholder = c2.ref
LEFT JOIN
users u ON
u.id = iR.author
LEFT JOIN
contacts c ON
c.ref = u.contactId
WHERE
(
iR.clientRef = '$clientRef' OR
iR.contactRef = '$contactRef'
)
AND
iR.projectRef = '$projectRef' AND
iR.type = 'Debrief'
GROUP BY
iR.linkId
ORDER BY
d.dateOfEngagement
";
By re-ordering my query I have managed to get both columns in... Thanks zerkms!
You cannot mix implicit joins and explicit joins in a single query in mysql.
So
FROM informationRelationships iR,
contacts c2
should be rewritten to
FROM informationRelationships iR
INNER JOIN contacts c2 ON ...
Do not use cartesian product and joins in the same query (not subquery), here, use only joins (CROSS JOIN is the same as cartesian product).