Count only unique terms based on inner SELECT JOIN - mysql

I'm trying to count only unique terms as a TOTAL count.
This is the original query and it works fine
->select('DISTINCT search_tags.term AS t_name, nbr', FALSE)
->from('search_tags LEFT JOIN (SELECT term AS tk, COUNT(search_tags.term) AS nbr FROM search_tags GROUP BY search_tags.term) AS TR ON search_tags.term = TR.tk ')
->where('search_tags.dt_added >=', '2011-08-01 09:48:54')
->where('search_tags.dt_added <=', '2011-09-02 09:48:54');
// returns: [twitter,12],[facebook,6].....
The thing is that this code runs a datatable (datatable.net) so the datatable removes the select line and change it to:
SELECT COUNT(*) AS numrows
FROM (search_tags LEFT JOIN (SELECT term AS tk, COUNT(search_tags.term) AS nbr FROM search_tags GROUP BY search_tags.term) AS TR ON search_tags.term = TR.tk)
WHERE `search_tags`.`dt_added` >= '2011-08-01 09:48:54'
AND `search_tags`.`dt_added` <= '2011-09-02 09:48:54'
// returns the same [twitter,12],[facebook,6]..... BUT the pagination is broken.
So the datatable can count the rows and use it as a pagination param.
But when it removes the select, it get all the rows as the DISTINCT is not there anymore.
I'm sleep deprived so I'm like stuck on try and error forever. Please help lol :P

Sorted out
->select('DISTINCT st5.term AS t_name, n_ocurrences', FALSE)
->from("search_tags AS st4
RIGHT OUTER JOIN (SELECT DISTINCT st.term, n_ocurrences
FROM search_tags AS st
JOIN
(SELECT term AS n_term, COUNT(term) AS n_ocurrences
FROM search_tags AS st2
GROUP BY st2.term)
AS st3 ON st3.n_term = st.term
WHERE st.dt_added >= '$min'
AND st.dt_added <= '$max') AS st5 ON st5.term = 1");
Had to add some inception selects to retrieve the right amount.
Now I need to count the UNIQUE n_ocurrences under the $min, $max as the n_ocurrences is returning only the overall count.

Related

Getting wrong COUNT values in query

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.

I want duplicates to be included with my in () statement

I want to include duplicates into my query. I havent succeeded in changing my "in" statements to "joins".
My expected result is a row count of 115.
My result is a row count of 108.
If i do a "Group by" in my first subquery, i get a row count of 108.
select match_id item_0, item_1, item_2, item_3, item_4, item_5, purchase_log
from player_matches where match_id IN
(select x.match_id from (select matches.match_id, picks_bans.team from matches, picks_bans where picks_bans.hero_id = 1 and picks_bans.match_id = matches.match_id and is_pick = true and start_time > 1483228800 ORDER BY start_time DESC) as x
inner join
(select matches.match_id, picks_bans.team from matches, picks_bans where picks_bans.hero_id
/*this is the statement that needs to be tweaked/changed */
IN (2,12,47,4,99) and picks_bans.match_id = matches.match_id and is_pick = true and start_time > 1483228800 ORDER BY start_time DESC) as y on y.match_id=x.match_id and x.team!=y.team)
and hero_id = 1
You can use the opendota inbrowser data-explorer to get a better understanding of my problem.
My subquery (returns 115)
My final Query (returns 108)
How do i get my final query to return 115 row counts?
My query is also really slow, is this because im using "in ()"?
It is because the IN will just check if the value is present. Use INNER JOIN instead:
select a.match_id, a.item_0, a.item_1, a.item_2, a.item_3, a.item_4, a.item_5, a.purchase_log
from player_matches a
INNER JOIN
(
select x.match_id from (select matches.match_id, picks_bans.team from matches, picks_bans where picks_bans.hero_id = 1 and picks_bans.match_id = matches.match_id and is_pick = true and start_time > 1483228800 ORDER BY start_time DESC) as x inner join (select matches.match_id, picks_bans.team from matches, picks_bans where picks_bans.hero_id in (2,12,47,4,5) and picks_bans.match_id = matches.match_id and is_pick = true and start_time > 1483228800 ORDER BY start_time DESC) as y on y.match_id=x.match_id and x.team!=y.team
) b ON a.match_id = b.match_id
WHERE hero_id = 1
Here's a demo from your original link.

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.

mysql query group by totals

I am using the following query to retrieve the number of events per state from 2 tables that are linked by a userID.
SELECT state,COUNT(*) AS num
FROM tableUserInfo
WHERE userID IN (SELECT userID
FROM tableEvents
WHERE conditionOne = 1
AND conditionTwo = 2)
GROUP BY state
This query works correctly. My problem is that not all states have user entries, and I need the query to return 0 for those. I was wondering if there was a method such as joining or using an in clause, that would included a set of all states, making the query return 0 for any that didn't have entries in tableEvents?
Do you have a list of states? If not then this would give a list of all the states your database knows about:
SELECT DISTINCT state FROM tableUserInfo
....and enclosing this in brackets it can be dropped in place in the query below:
SELECT s.state, IFNULL(cnt, 0) AS num
FROM list_of_states s
LEFT JOIN (
SELECT state,COUNT(*) AS cnt
FROM tableUserInfo ui
INNER JOIN tableEvents te
ON ui.userId=te.userId
WHERE conditionOne = 1
AND conditionTwo = 2
GROUP BY state
) u
ON s.state=u.state;
Although in the absence of "list_of_states" it would be more efficient to do this:
SELECT ui.state, SUM(IF(te.userId IS NULL, 0, 1)) AS cnt
FROM tableUserInfo ui
LEFT JOIN tableEvents te
ON ui.userId=te.userId
AND te.conditionOne = 1
AND te.conditionTwo = 2
GROUP BY state;
As #raymond-nijland suggested you can use Left Join to include all states.
SELECT tableUserInfo.state,COUNT(tableUserInfo.*) AS num
FROM tableUserInfo Left Join tableEvents on tableUserInfo.userID = tableEvents.userID
WHERE tableEvents.conditionOne = 1 AND tableEvents.conditionTwo = 2
GROUP BY state

Subquery Slows Query down significantly

I'm trying to do a query that replaces multiple queries to produce a result set. I've got a fairly straight forward set of 1 to 1 joins, but one column I'm trying to get from a table that keeps multiple records per primary record. Basically it's like this:
meet_entries with a primary key id column and a bunch of other columns,
meet_entries_statuses, with an autoincrement id column and a foreign key to the id column of meet_entry
There may be multiple rows in meet_entry_statuses for each row in meet_entries. In my query, I'm trying to get the most recently added(so highest id number) row associated with the meet_entry primary key id.
Here's my query:
SELECT
meet_entries.id,
member.firstname,
member.surname,
member.gender,
member.dob,
clubs.code,
clubs.clubname,
meet_entries.meals,
meet_entries.massages,
meet_entries.cost,
meet_entries.cancelled,
(SELECT meet_entry_status_codes.description
FROM meet_entry_statuses, meet_entry_status_codes
WHERE meet_entry_statuses.code = meet_entry_status_codes.id
AND meet_entry_statuses.id = meet_entries.id
ORDER BY meet_entry_statuses.id DESC
LIMIT 1) as status,
COUNT(DISTINCT meet_events_entries.id) as entries
FROM meet_entries, meet_events_entries, member, clubs, meet_entry_statuses, meet_entry_status_codes
WHERE meet_entries.meet_id = ?
AND meet_entries.id = meet_events_entries.meet_entry_id
AND meet_entries.member_id = member.id
AND meet_entries.club_id = clubs.id
GROUP BY meet_entries.id
;
Adding the bit:
(SELECT meet_entry_status_codes.description
FROM meet_entry_statuses, meet_entry_status_codes
WHERE meet_entry_statuses.code = meet_entry_status_codes.id
AND meet_entry_statuses.id = meet_entries.id
ORDER BY meet_entry_statuses.id DESC
LIMIT 1) as status,
takes the query from being .2 of a second, to never finishing. There are only 10 matching rows in meet_entries. There are about 50 rows in the meet_entries_statuses appropriate to the 10 rows in meet_entries, but as I say I'm trying to only get 1 row for each meet_entries row. Any suggestions on a better way to do this?
I am not very sure why you would join with meet_entry_statuses and meet_entry_status_codes without any join conditions. Doing so means that you are doing a cross join. So if there are N rows in meet_entries, and M and P rows in the above two tables respectively, you end up generating N x M x P rows.
Can you try taking out the two joins. I marked them out in the following rewritten query:
SELECT
meet_entries.id,
member.firstname,
member.surname,
member.gender,
member.dob,
clubs.code,
clubs.clubname,
meet_entries.meals,
meet_entries.massages,
meet_entries.cost,
meet_entries.cancelled,
(SELECT
meet_entry_status_codes.description
FROM
meet_entry_statuses as mes
, meet_entry_status_codes as mesc
WHERE
meet_entry_statuses.code = meet_entry_status_codes.id
AND meet_entry_statuses.id = meet_entries.id
ORDER BY meet_entry_statuses.id DESC
LIMIT 1
) as status,
COUNT(DISTINCT meet_events_entries.id) as entries
FROM
meet_entries as me
, meet_events_entries as mee
, member as m
, clubs as c
, meet_entry_statuses as mes -- try taking this out
, meet_entry_status_codes as mesc -- try taking this out
WHERE
meet_entries.meet_id = ?
AND meet_entries.id = meet_events_entries.meet_entry_id
AND meet_entries.member_id = member.id
AND meet_entries.club_id = clubs.id
GROUP BY meet_entries.id
;