how to simplify my sql query - mysql

I have this query, but it takes about 15 seconds to finish.. how can i simplyfy it to get same result in less time? my problem is that i need all of this data at ones.
SELECT * FROM (
SELECT c.client_id, c.client_name, c.client_bpm,
c.client_su_name, c.client_maxbpm, s.bpm,
s.timestamp, m.mesure_id, ms.currentT
FROM tbl_clients c, tbl_meting m, tbl_sensor_meting s,
tbl_magsens_meting ms
WHERE c.client_id = m.client_id
AND (m.mesure_id = s.id_mesure
OR m.mesure_id = ms.id_mesure)
AND m.live =1
ORDER BY s.timestamp DESC
) AS mesure
GROUP BY mesure.client_id

I think the problem may be the OR condition from your WHERE clause? You seem to be trying to join to one table or another, which you can't do. So I've replaced it with a LEFT JOIN, so in the event no related records exist nothing will be returned.
I also took out your GROUP BY, as I don't think it was required.
SELECT c.client_id, c.client_name, c.client_bpm,
c.client_su_name, c.client_maxbpm, s.bpm,
s.timestamp, m.mesure_id, ms.currentT
FROM tbl_clients c
JOIN tbl_meting m ON m.client_id = c.client_id
LEFT JOIN tbl_sensor_meting s ON s.id_mesure = m.mesure_id
LEFT JOIN tbl_magsens_meting ms ON ms.id_mesure = m.mesure_id
WHERE m.live = 1
ORDER BY s.timestamp DESC

Related

how to eliminate union for better performance in mysql

Hi i want fetch the records depends on different condition i used union worked fine but taking more than 15 secs so how can we eliminate union or make the query faster
QUERY:
(SELECT p.professional_id,
p.company_name,
pbt.name AS professional_business_type_name,
pbtm.kukun_url,
p.kukun_score,
cc.year_founded,
p.contractor_category,
p.permit_data_count,
p.cost_range_code,
fpcr.cost_min_value,
fpcr.cost_max_value
FROM professional p
INNER JOIN company_contact cc
ON cc.company_contact_id = p.company_contact_id
INNER JOIN professional_business_type_map AS pbtm
ON pbtm.professional_id = p.professional_id
INNER JOIN of_professional_business_type_organization AS pbt
ON pbt.professional_business_type_organization_id =
pbtm.professional_business_type_organization_id
INNER JOIN f_professional_cost_range fpcr
ON fpcr.cost_range_code = p.cost_range_code
WHERE p.professional_id != 262100
AND cc.company_city_id = 5229
AND pbt.professional_business_type_organization_id = 2
AND p.cost_range_code = 4
ORDER BY p.kukun_score DESC
LIMIT 5)
UNION
(SELECT p.professional_id,
p.company_name,
pbt.name AS professional_business_type_name,
pbtm.kukun_url,
p.kukun_score,
cc.year_founded,
p.contractor_category,
p.permit_data_count,
p.cost_range_code,
fpcr.cost_min_value,
fpcr.cost_max_value
FROM professional p
INNER JOIN company_contact cc
ON cc.company_contact_id = p.company_contact_id
INNER JOIN professional_business_type_map AS pbtm
ON pbtm.professional_id = p.professional_id
INNER JOIN of_professional_business_type_organization AS pbt
ON pbt.professional_business_type_organization_id =
pbtm.professional_business_type_organization_id
INNER JOIN f_professional_cost_range fpcr
ON fpcr.cost_range_code = p.cost_range_code
WHERE p.professional_id != 262100
AND cc.company_city_id = 5229
AND pbt.professional_business_type_organization_id = 2
ORDER BY p.kukun_score DESC
LIMIT 5)
UNION
(SELECT p.professional_id,
p.company_name,
pbt.name AS professional_business_type_name,
pbtm.kukun_url,
p.kukun_score,
cc.year_founded,
p.contractor_category,
p.permit_data_count,
p.cost_range_code,
fpcr.cost_min_value,
fpcr.cost_max_value
FROM professional p
INNER JOIN company_contact cc
ON cc.company_contact_id = p.company_contact_id
INNER JOIN professional_business_type_map AS pbtm
ON pbtm.professional_id = p.professional_id
INNER JOIN of_professional_business_type_organization AS pbt
ON pbt.professional_business_type_organization_id =
pbtm.professional_business_type_organization_id
INNER JOIN f_professional_cost_range fpcr
ON fpcr.cost_range_code = p.cost_range_code
WHERE p.professional_id != 262100
AND cc.company_city_id = 5229
ORDER BY p.kukun_score DESC
LIMIT 5)
UNION
(SELECT p.professional_id,
p.company_name,
pbt.name AS professional_business_type_name,
pbtm.kukun_url,
p.kukun_score,
cc.year_founded,
p.contractor_category,
p.permit_data_count,
p.cost_range_code,
fpcr.cost_min_value,
fpcr.cost_max_value
FROM professional p
INNER JOIN company_contact cc
ON cc.company_contact_id = p.company_contact_id
INNER JOIN professional_business_type_map AS pbtm
ON pbtm.professional_id = p.professional_id
INNER JOIN of_professional_business_type_organization AS pbt
ON pbt.professional_business_type_organization_id =
pbtm.professional_business_type_organization_id
INNER JOIN f_professional_cost_range fpcr
ON fpcr.cost_range_code = p.cost_range_code
WHERE p.professional_id != 262100
AND cc.company_state_id = 5
ORDER BY p.kukun_score DESC
LIMIT 5)
LIMIT 5;
(Likely Bug) You need ORDER BY p.kukun_score DESC before the UNION's LIMIT 5. Today MySQL may sequentially perform all parts of the UNION, combine all of them, then do the LIMIT. In some future version, it is likely to, for example, perform the SELECTs in parallel, thereby jumbling the results.
Hence if you want the rows from the first SELECT to be delivered first, you must add a column and ORDER BY.
( SELECT 1 AS sequence, ... )
UNION ALL
( SELECT 2 AS sequence, ... )
...
ORDER BY sequence, kukun_score DESC
LIMIT 5
Also, UNION is the same as UNION DISTINCT, which add a de-dup pass to the operation. That is, the semantics requires evaluating all the selects.
These INDEXes may help:
cc: (company_state_id, company_contact_id, year_founded)
cc: (company_city_id, company_contact_id, year_founded)
fpcr: (cost_range_code, cost_max_value, cost_min_value)
Those indexes will be "covering" and optimal for the SQL you have.
Some benefit will come from moving fpcr out of the union. That is, first UNION all the other tables, then JOIN to fpcr. to get the two columns from it. This will speed things up because it it needs to reach into that table only 5 times, instead of thousands times (however many rows are in the 4 temporary tables).

Mysql error Invalid use of group function

select
c.investor_id as investorid,
i.name as investor_name,
inv_typ.name as type_of_investor,
(select count(*) from investor_users where user_id=iu.user_id) as num_of_investors,
(select count(*) from task_logs where campaign_id=c.id) as num_of_task_logs,
c.updated_at as updated_date,
c.call_date as calldate,
a.name as admin_name,
c.id as campaign_id
from
admins a,
investors i,
investor_types inv_typ,
campaigns c,
task_logs tl,
campaign_statuses cs,
investor_users iu
where
c.investor_id=i.id
and i.investor_type_id=inv_typ.id
and i.id=iu.investor_id
and c.campaign_status_id = cs.id
and c.assigned_to_admin_id = a.id
and c.campaign_type_id = 1
and c.campaign_status_id = (select id from campaign_statuses having id=c.campaign_status_id and cs.code ='CLOSED') and c.assigned_to_admin_id = 46
and tl.campaign_id = c.id and max((select task_logs.task_status_id from task_logs having task_logs.campaign_id = c.id)) = 9
order by c.call_date ASC
You have a max() in the where clause:
max((select task_logs.task_status_id
from task_logs
having task_logs.campaign_id = c.id)) = 9
That is an improper use of an aggregation function. Instead:
(select max(task_logs.task_status_id)
from task_logs
where task_logs.campaign_id = c.id) = 9
This glaring error was easy to spot, because it is so audacious. However, your query would benefit from the following:
Never use commas in the FROM clause. Always use proper explicit JOIN syntax. That is the proper way to express joins for two decades, so it is time for everyone to use it.
Use table aliases so queries are easier to write and to read.
Don't confuse the having clause with the where clause. That subquery should have used where.

Trying to add one last SUM() column to my query in SQL Server 2008

I have the first query which is producing correct results. What I need is I need to add the sum of values as a last column grouped by surveyid. I can't insert Sum(c.value) into the first query because it is an aggregate function. I have the correct query as my second query below. I know there's pivot functionality but not sure if it can be used here. I do realize that there will be repetition but that's okay.
'first query
SELECT
A.PATIENTID, B.STUDENTNUMBER, c.surveyid,
convert(varchar, A.CreatedDate, 107),
C.QuestionID, C.Value, D.Question
FROM
dbo.Survey A, dbo.Patient B, [dbo].[SurveyQuestionAnswer] C, [dbo].[LookupQuestions] D
WHERE
A.PATIENTID = B.ID
and c.SurveyID = A.ID
and c.QuestionID = d.ID
and c.questionid <> 10
ORDER BY
A.PATIENTID
'second query
select
c.surveyid,SUM(c.value) as scores
from
dbo.SurveyQuestionAnswer c
group by
c.SurveyID
order by
SurveyID '---not important
You can use SUM if you add the OVER clause. In this case:
SELECT
A.PATIENTID, B.STUDENTNUMBER, c.surveyid,
convert(varchar, A.CreatedDate, 107),
C.QuestionID, C.Value, D.Question,
SUM(c.Value) OVER(PARTITION BY c.surveyid) scores
FROM
dbo.Survey A
INNER JOIN dbo.Patient B
ON A.PATIENTID = B.ID
INNER JOIN [dbo].[SurveyQuestionAnswer] C
ON c.SurveyID = A.ID
INNER JOIN [dbo].[LookupQuestions] D
ON c.QuestionID = d.ID
WHERE
c.questionid <> 10
ORDER BY
A.PATIENTID
You could use something like this:
SELECT
s.PATIENTID, p.STUDENTNUMBER, sqa.surveyid,
CONVERT(varchar, s.CreatedDate, 107),
sqa.QuestionID, sqa.Value, lq.Question,
Scores = (SELECT SUM(Value) FROM dbo.SurveyQuestionAnswer s2 WHERE s2.SurveyID = s.ID)
FROM
dbo.Survey s
INNER JOIN
dbo.Patient p ON s.PatientID = p.ID
INNER JOIN
[dbo].[SurveyQuestionAnswer] sqa ON sqa.SurveyID = s.ID
INNER JOIN
[dbo].[LookupQuestions] lq ON sqa.QuestionID = lq.ID
WHERE
sqa.questionid <> 10
ORDER BY
s.PATIENTID
By having a subquery with the SUM(...) you should be able to get that sum as a single value and you don't need to use any grouping function

MySQL sum of sub queries

I have quite a long query that is causing me some problems. For the first sub-query I keep getting the error: "MySQL server version for the right syntax to use near 'SELECT project.project_total_num_hours_quoted FROM project inner join time_recor' at line 5".
The subquery in question is:
sum(SELECT
project.project_total_num_hours_quoted
FROM
project inner join time_recording using(project_id)
WHERE
project.company_id = company.company_id
AND project_is_retainer != 1
AND time_recording.time_recording_event_start_datetime >= '2011-01-01' AND time_recording.time_recording_event_stop_datetime <= '2011-03-01'
group by project_id
) AS hours_quoted,
This returns a set of results. In the larger query I simply want to have the sum.
SELECT
SUM((unix_timestamp(time_recording.time_recording_event_stop_datetime)-unix_timestamp(time_recording.time_recording_event_start_datetime))/3600) AS total_time,
company.company_label,
sum(SELECT
project.project_total_num_hours_quoted
FROM
project inner join time_recording using(project_id)
WHERE
project.company_id = company.company_id
AND project_is_retainer != 1
AND time_recording.time_recording_event_start_datetime >= '2011-01-01' AND time_recording.time_recording_event_stop_datetime <= '2011-03-01'
group by project_id
) AS hours_quoted,
(SELECT SUM(project.project_total_num_hours_quoted)
FROM project
INNER JOIN time_recording ON project.project_id = time_recording.project_id
WHERE time_recording.time_recording_event_start_datetime>='2011-01-01'
AND project_is_retainer!=1
AND time_recording.time_recording_event_stop_datetime<='2011-03-01'
AND project.company_id!=1
) AS total_hours_quoted,
(
SELECT
SUM((unix_timestamp(time_recording.time_recording_event_stop_datetime)-unix_timestamp(time_recording.time_recording_event_start_datetime))/3600)
FROM time_recording
INNER JOIN project ON time_recording.project_id = project.project_id
WHERE project.company_id!=1
AND project_is_retainer!=1
AND time_recording.time_recording_event_start_datetime>='2011-01-01'
AND time_recording.time_recording_event_stop_datetime<='2011-03-01'
)
AS total_hours
FROM time_recording
INNER JOIN project ON time_recording.project_id = project.project_id
INNER JOIN company ON project.company_id = company.company_id
WHERE company.company_id!=1
AND project_is_retainer!=1
AND time_recording.time_recording_event_start_datetime>='2011-01-01'
AND time_recording.time_recording_event_stop_datetime<='2011-03-01'
GROUP BY company.company_id
ORDER BY total_time desc
LIMIT 7
In your first subquery, you don't need the group by if you sum it in the outer query. And you are missing the ON clause.
SELECT project.project_total_num_hours_quoted
FROM project inner join time_recording
ON project.id=time_recording.project_id
WHERE
project.company_id = company.company_id
AND project_is_retainer != 1
AND time_recording.time_recording_event_start_datetime >= '2011-01-01'
AND time_recording.time_recording_event_stop_datetime <= '2011-03-01'
I would strongly recommend scrapping this and starting again.
Several, if not all, the subselects could be merged into a single SELECT statement. The outer SELECT is an aggregate operation which selects non-aggregated values not included in the GROUP BY clause. MySQL does not optimize push-predicates. And you've got redundant joins in the query.

MySQL: "Ignore" if a table row is missing during JOIN

I'm doing a LEFT JOIN on three tables, where the table "time" doesn't necessarily contain any matching rows. But if no matching rows is found in that table, the linked data disappears.
SELECT
w.date AS worker_date,
w.name AS worker_name,
w.address AS worker_address,
w.zip AS worker_zip,
w.place AS worker_place,
w.phone AS worker_phone,
w.email AS worker_email,
w.company AS worker_company,
w.accessibility AS worker_accessibility,
c.date AS client_date,
c.name AS client_name,
c.address AS client_address,
c.zip AS client_zip,
c.place AS client_place,
c.phone AS client_phone,
c.email AS client_email,
c.web AS client_web,
c.contact AS client_contact,
j.date AS job_date,
j.client_id,
j.worker_id,
j.name AS job_name,
j.description AS job_description,
j.type AS job_type,
j.status AS job_status,
j.proof AS job_proof,
j.deadline AS job_deadline,
j.price AS job_price,
j.final_client AS job_final_client,
SUM(t.hours) AS time_hours
FROM
jobs AS j
LEFT JOIN (
workers AS w,
clients AS c,
time AS t
) ON (
w.id = j.worker_id AND
c.id = j.client_id AND
j.id = t.job_id
) GROUP BY
j.id;
How can I make this work?
Thank you in advance.
add
WHERE t.job_id IS NOT NULL before GROUP BY
Try Replace
SUM(t.hours) AS time_hours
to
(SELECT IFNULL(SUM(t.hours),0) FROM time WHERE time.job_id=j.job_id) AS time_hours
And remove the time from the join
I think your basic query is correct (with the join under braces)
Just replace
SUM(t.hours) AS time_hours
with
SUM(if(t.hours is NULL,0,t.hours)) AS time_hours
I am not sure if this is the problem here, but the behavior of commas vs JOINs changed after a certain MySQL version. Try this
...
FROM jobs AS j LEFT JOIN workers AS w ON w.id = j.worker_id
LEFT JOIN clients AS c c.id = j.client_id
LEFT JOIN `time` AS t ON j.id = t.job_id
...
Also modify the SUM with IFNULL as #ajreal suggests.