Getting wrong COUNT values in query - mysql

I am using the following query to get COUNT items from rows from the same table in LEFT JOIN.
This is the query:
SELECT
pac.id_sat as id_sat,
pac.nombre_contacto as nombre_contacto,
pac.centro_contacto as centro_contacto,
pac.tel_contacto as tel_contacto,
pac.horario_contacto as horario_contacto,
pac.email_contacto as email_contacto,
pac.num_factura as num_factura,
pac.fecha_factura as fecha_factura,
eq.nombre_equipo as modelo_equipo,
pac.num_serie as num_serie,
pac.tipo_incidencia as tipo_incidencia,
pac.cod_sat as cod_sat,
pac.estado as estado,
pac.clinica as clinica,
pac.fecha_sat as fecha_sat,
COUNT(medfotos.id_media_sat) as num_fotos,
COUNT(medvideos.id_media_sat) as num_videos
FROM tb_sat pac
LEFT JOIN tb_equipos eq ON pac.modelo_equipo = eq.id_equipo
LEFT JOIN tb_media_sat medfotos ON pac.cod_sat = medfotos.cod_sat AND medfotos.tipo = 1
LEFT JOIN tb_media_sat medvideos ON pac.cod_sat = medvideos.cod_sat AND medvideos.tipo = 2
WHERE pac.clinica = '".$idclinica."'
GROUP BY pac.id_sat
ORDER BY pac.fecha_sat DESC
My issue is that I am getting a wrong amount of COUNT items.
The real value for num_fotos should be 3 and for num_videos should be 2.
I am getting num_fotos = 6 and num_videos = 6.
EDIT
Table tb_sat
Table tb_media_sat

Sub-query will work better in your case like as follows:
SELECT pac.*, (SELECT COUNT(id_media_sat) FROM tb_media_sat WHERE cod_sat=pac.cod_sat AND tipo=1) AS num_fotos, (SELECT COUNT(id_media_sat) FROM tb_media_sat WHERE cod_sat=pac.cod_sat AND tipo=2) AS num_videos FROM tb_sat pac WHERE pac.clinica = '".$idclinica."' ORDER BY pac.fecha_sat DESC
Rest columns, please add yourself slowly slowly. I hope you will get correct output.

Related

Database view taking too long time to fetch data when using order by clause

I have created view which has more than 20 thousand records and executing a query on same view, its taking too long time to fetch only 20 records using limit.
If I removed ORDER BY clause then same query gives result within fraction of sec.
Even I tried that, applied order by condition on view so that I can execute query without ORDER BY clause but still query taking 1.1 min to 1.8 min to return result.
Here is the query :
SELECT full_name, project_no, customer_name, description, status, comments,
FROM (view_project)
WHERE labor_code IS NOT NULL
LIMIT 20
Definition of view :
select a.id AS id,a.tms_id AS tms_id,a.date AS date_from,a.hour AS hour,a.hour_ot AS hour_ot,a.hour_dt AS hour_dt,a.function AS function,a.billable AS billable,a.qb_class AS qb_class,a.comments AS comments,b.extra_fields AS extra_fields,a.labor_code AS labor_code,a.cost AS cost,a.bill AS bill,a.pr_cost AS pr_cost,a.pr_bill AS pr_bill,b.user_id AS user_id,b.date_from AS date_from_b,b.date_to AS date_to,c.full_name AS full_name,c.username AS username,d.name AS name,d.project_no AS project_no,d.id AS project_id,e.description AS description,f.name AS customer_name,concat(b.date_from,'|',b.date_to) AS week_range,a.data_row AS data_row,if((isnull(g.tms_row_status) or (g.tms_row_status = '')),'No Status',g.tms_row_status) AS status,ifnull(h.submit_entity,'') AS submit_entity,a.tms_row_uuid AS tms_row_uuid from (((((((labor_time_tracking a left join timesheet b on((a.tms_id = b.id))) left join user c on((b.user_id = c.id))) left join project d on((a.project_id = d.id))) left join supplier f on((d.customer_id = f.id))) left join item e on((convert(a.labor_code using utf8) = e.uuid))) left join labor_time_tracking_rows g on((a.tms_row_uuid = g.tms_row_uuid))) left join timesheet_submission h on(((a.tms_id = h.tms_id) and (a.project_id = h.project_id) and (a.data_row = h.tms_row_id)))) order by b.id desc

SQL error as a result of rewriting a query using subquery into a query using join

The original query:
SELECT o.offering_number,
o.english_description,
o.french_description,
fop.price_amount,
fop.price_type_code,
fop.price_status_code,
fop.offering_id,
(SELECT fop1.price_amount from facility_offering_price fop1
WHERE fop.offering_id = fop1.Offering_Id
AND fop1.price_type_code = 5
AND fop1.price_status_code = 3
) as 'priceAmount'
from facility_offering_price fop
join offering o on fop.offering_id = o.offering_id
WHERE fop.price_start_date = '15-10-28'
AND fop.price_status_code IN (1,2)
/*AND (price_status_code IS NULL)*/
AND fop.price_type_code = 5
/*AND (o.offering_number IS NULL)*/
ORDER BY o.offering_number ASC, fop.price_sequence_number ASC;
It produces a result of one entry.
The result query:
SELECT o.offering_number,
o.english_description,
o.french_description,
fop.price_amount,
fop2.price_amount,
fop.price_type_code,
fop.offering_id,
fop2.offering_id
from facility_offering_price fop
join offering o on fop.offering_id = o.offering_id
inner join
(select
fop1.offering_id,
fop1.price_amount
from facility_offering_price fop1
WHERE fop1.price_type_code = 5
AND fop1.price_status_code = 3
) fop2 on fop.offering_id = fop2.offering_id
WHERE fop.price_start_date = '15-10-28'
AND fop.price_status_code IN (1,2)
/*AND (price_status_code IS NULL)*/
AND fop.price_type_code = 5
/*AND (o.offering_number IS NULL)*/
ORDER BY o.offering_number ASC, fop.price_sequence_number ASC;
It's result set is empty. However, an entry is found if I ask for fop1.price_status_code = 1.
Unable to wrap my head around this one I would appreciate your help.
Try using LEFT JOIN instead. The conversion from SELECT a, subquery AS val FROM ... to a join is more accurately reflected that way. The original query would return rows with NULL val when the subquery has no results; your version ends up omitting such rows completely.

Order query output according to 'is in table/ is not in table'

I have the following Database Design:
Database Design
I want to get all Information from table 'info' where the id IS NOT in table 'archived'. To do so I wrote:
SELECT *
FROM traffic_info i
LEFT JOIN
traffic_info_archived a ON (i.info_id = a.info_id)
WHERE
i.branch_id = 4 AND i.user_id = 7 a.info_id IS NULL ORDER BY i.info_date_from ASC
This works as expected.
The next challenge is to only show information that are also included in the 'published' table. To get this done I have expanded my previous query to :
SELECT *
FROM traffic_info i
LEFT JOIN
traffic_info_archived a ON (i.info_id = a.info_id)
RIGHT JOIN
traffic_info_publised p ON (i.info_id = p.info_id)
WHERE
i.branch_id = 4 AND a.info_id AND i.user_id = 7 IS NULL ORDER BY i.info_date_from ASC
This does also work as expected.
The final challenge is to Order this result according to table 'read'. Information´s id that are NOT in table 'read' should be ordered ASC. But even if its id does not appear in table 'read' they should not be excluded from the query output. BUT the primary ORDER should be
i.info_date_from ASC
I hope this is understandable, my English is not the best :) If not, please comment and I will do my best to make it understandable. Hope some can help!
I´ve tried to create a SQLFiddle, but I wasn´t able to create a runnable example, sorry for that.
UPADTE:
Using the approach from #Dylan Su
SELECT *
FROM traffic_info i
LEFT JOIN
traffic_info_archived a ON (i.info_id = a.info_id)
INNER JOIN
traffic_info_publised p ON (i.info_id = p.info_id)
WHERE
i.branch_id = 4 AND a.info_id AND i.user_id = 7 IS NULL
ORDER BY
CASE WHEN NOT EXISTS(SELECT 1 FROM read WHERE i.info_id = read.info_id)
THEN i.info_date_from END ASC;
the goal is nearer then it ever was :)
Sample Data output
Both entries marked with a red "X" are in table read. Therefore id 3 should be last the, in the middle 1 and 2 at the top.
So the last thing to archive is to do the correct order of table read. I´ve tried sth like:
(SELECT 1 FROM traffic_info_read WHERE i.info_id = traffic_info_read.info_id ORDER BY traffic_info_read.info_id DESC)
But that didn´t had any influnce.
Try this:
SELECT *
FROM traffic_info i
LEFT JOIN
traffic_info_archived a ON (i.info_id = a.info_id)
INNER JOIN
traffic_info_publised p ON (i.info_id = p.info_id)
WHERE
i.branch_id = 4 AND a.info_id AND i.user_id = 7 IS NULL
ORDER BY
EXISTS(SELECT 1 FROM read WHERE i.info_id = read.info_id) ASC,
i.info_date_from ASC;
The Answer of #Dylan Su is absolutely correct and I won´t unmark it as accepted.
However, based on the Information I gained from the conversation I have created another solution, that doesn´t make use of sub query.
I heard that using just JOIN´s will result in better performance, I don´t know if it´s correct and I don´t have that much test data currently to find out, but here is the solution using no sub query.
SELECT *
FROM traffic_info i
LEFT JOIN
traffic_info_archived a ON (i.info_id = a.info_id)
INNER JOIN
traffic_info_published p ON (i.info_id = p.info_id)
LEFT JOIN
traffic_info_read r ON (i.info_id = r.info_id)
WHERE
i.branch_id = 4 AND a.info_id IS NULL ORDER BY r.info_id IS NULL DESC, i.info_date_from ASC
;

Insert a parameter into Where Clause

I have this query which i want to get rank from the data on my database
set #urut:=0;
set #rankhrg:=0;
select #urut:=#urut+1 as urut, a.id_tender, b.nama_tender, b.nomor_tender, b.tgl_close1 as tgl_close,
(SELECT rankhrg
from (select sum(tot_harga) as hrg_twr, id_rekanan, id_tender, #rankhrg:=#rankhrg+1 as rankhrg from tb_real_barang where id_tender = s.id_tender group by id_rekanan) as rank_harga
left join tb_master_tender s on s.id_tender = b.id_tender
where rank_harga.id_rekanan = a.id_rekanan
order by rank_harga.hrg_twr asc) as ranking
from tb_real_tender a
left join tb_master_tender b on a.id_tender = b.id_tender
where a.id_rekanan = 1
order by convert(a.id_tender,unsigned) desc
i want to pass id_tender into the select inside the select when i want to get rankhrg :
select sum(tot_harga) as hrg_twr, id_rekanan, id_tender,
#rankhrg:=#rankhrg+1 as rankhrg
from tb_real_barang
where id_tender = s.id_tender
group by id_rekanan
but I always get error that said that s.id_tender is unknown in where clause.
can someone guide me how to pass the parameter into that insert?
thank you :)
You are not joining with that table tb_master_tender and neither it's present in outer query FROM clause. So, you need to do a JOIN separately for that inner query like below
select sum(trb.tot_harga) as hrg_twr,
trb.id_rekanan,
trb.id_tender,
#rankhrg:=#rankhrg+1 as rankhrg
from tb_real_barang trb
left join tb_master_tender s on trb.id_tender = s.id_tender
group by trb.id_rekanan

Incorrect SUM when using two LEFT JOINs and a GROUP BY

The following code returns an incorrect value for the sumHours field. It appears to prepare the sumHours field then once the GROUP BY runs, sum the sums together.
SELECT mmr_ID, mmr_projectName, SUM(mmr_hoursWorked.mmr_hoursWorked_hours) AS sumHours
FROM mmr
LEFT JOIN mmr_hoursWorked
ON mmr.mmr_ID = mmr_hoursWorked.mmr_hoursWorked_project AND mmr_hoursWorked.mmr_hoursWorked_mm = "P90826"
LEFT JOIN mmr_notes
ON mmr.mmr_ID = mmr_notes.mmr_notes_MMR_ref AND mmr_notes.mmr_notes_author = "P90826"
WHERE mmr_mmAssigned = "P90826" AND mmr_projectStatus != 1 OR mmr_notes.mmr_notes_author = "P90826" AND mmr_projectStatus != 1
GROUP BY mmr_ID
Actual Results
mmr_ID - 35
mmr_projectName - Project A
sumHours - 140.2
Expected Results
mmr_ID - 35
mmr_projectName - Project A
sumHours - 35.05
Due to JOIN statements combination of results are returned, so you should handle aggregates and joins separately. Try this:
SELECT t.*
FROM
(
SELECT mmr_ID, mmr_projectName, SUM(mmr_hoursWorked.mmr_hoursWorked_hours) AS sumHours
FROM mmr
LEFT JOIN mmr_hoursWorked
ON mmr.mmr_ID = mmr_hoursWorked.mmr_hoursWorked_project AND mmr_hoursWorked.mmr_hoursWorked_mm = 'P90826'
WHERE mmr_projectStatus != 1 AND mmr_mmAssigned = 'P90826'
GROUP BY mmr_ID, mmr_projectName, mmr_mmAssigned
) t
LEFT JOIN mmr_notes
ON t.mmr_ID = mmr_notes.mmr_notes_MMR_ref
WHERE mmr_notes.mmr_notes_author = 'P90826';
The issue was corrected by normalizing the database. The mmr_notes table was integrated into the mmr_hoursWorked table since it only had one unique field.