Count of joined items per group in MySql - mysql

I need to get a set of results showing the number of items accumulated for each 'esta' group.
I'm grouping the results by establishment.
Establishment is inner joined to base.
Left joined items are joined against the base.
So in Esta group 2, let's say there are 3 base ids. Each written and verbal record attached to the base ID would count towards that esta in the results set. There can be multiple 'written' or 'verbal' attached to each base record.
I have 6 verbals and 4 writtens in the database, they are spread around the different 'esta' records. In my query, they are all counting towards the first row of the result I get.
I have tried the same with much more data, and regardless of the 'esta', the first row contains every left joined element counted together.
sql:
SELECT
esta.enf_esta_id
,SUM(IF(verbal.enf_verbal_id is not null,1,0)) as verbals
,SUM(IF(written.enf_written_id is not null,1,0)) as writtens
FROM
enf_base base
INNER JOIN enf_esta esta ON esta.enf_esta_id = base.enf_esta_id
LEFT JOIN enf_verbal verbal ON verbal.enf_base_id = base.enf_base_id
LEFT JOIN enf_written written ON written.enf_base_id = base.enf_base_id
WHERE
1=1
GROUP BY
esta.enf_esta_id
result:
enf_esta_id verbals writtens
2 10 10
3 1 0
4 1 1
6 0 0
To prove that the top row is incorrect, here are the results of just getting the verbals and writtens from enf_esta_id 2.
SELECT
COUNT( * ) AS total
FROM
enf_written
INNER JOIN enf_base ON enf_base.enf_base_id = enf_written.enf_base_id
INNER JOIN enf_esta ON enf_base.enf_esta_id = enf_esta.enf_esta_id
WHERE
enf_esta.enf_esta_id =2
yields:
5
And the same with enf_verbal yields 2. adding up the totals of each gives us the correct 10 if we discount the top row of the problem query result.
Can anyone help me get the result I need?

You are multiplying. Say there are 2 verbals and 5 writtens then your joins make these 10 records (i.e. all combinations). Rather then joining tables and aggregating then, you should first aggregate and then join your aggregates. In your case this is aggregates per base ID, which you will finally further aggregate to get estas.
select
base.enf_esta_id,
coalesce(sum(verbal.cnt), 0) as verbals,
coalesce(sum(written.cnt), 0) as writtens
from enf_base base
left join
(
select enf_base_id, count(*) as cnt
from enf_verbal
group by enf_base_id
) verbal on verbal.enf_base_id = base.enf_base_id
left join
(
select enf_base_id, count(*) as cnt
from enf_written
group by enf_base_id
) written on written.enf_base_id = base.enf_base_id
group by base.enf_esta_id;

Related

sql query group by not working in subquery

I have a sql query based on 2 IDs in the same table, the results of the sum have come out correctly, but the problem is group by cannot handle data that appears 2 times
SELECT coa_a.debet_april,coa_a.namacoaapril, coa_b.kredit_april ,coa_b.namacoaapril
FROM `t_jurnalumum` join coa on coa.m_coa_4_id=t_jurnalumum.IdDebet
join (select DISTINCT m_coa_4_id, sum(a.Nilai) as debet_april, coa.namacoa as namacoaapril
from t_jurnalumum a j
join coa on a.IdDebet=coa.m_coa_4_id
where year (a.Tanggal)=2021 and month (a.Tanggal)=4
GROUP by a.IdDebet ) as coa_a on coa_a.m_coa_4_id=t_jurnalumum.IdDebet
join (select DISTINCT m_coa_4_id, sum(b.Nilai) as kredit_april, coa.namacoa as namacoaapril
from t_jurnalumum b
join coa on b.IdKredit=coa.m_coa_4_id
where year (b.Tanggal)=2021 and month (b.Tanggal)=4
GROUP by b.IdKredit ) as coa_b on coa_b.m_coa_4_id=t_jurnalumum.IdKredit
GROUP by coa_b.namacoaapril, coa_a.namacoaapril
this the result
and this is the main table
It is because you are using the same table. The first sub query of join will give you the distinct value from first group by and second group by gives distinct value. And at the end you also have grouped the whole result. The first one gives two distinct value and second one gives two distinct value which eventually gives all value.

Getting the count of result respect to a column

My
select distinct c.*
from kuponbahis c
join bahis b on b.sonuc = c.secim and b.ID=c.bahis AND c.durum=0
Query is giving the result as;
How can I get the count of results respect to their "kupon" field.
Expected result;
32, 3
33, 2
Thank you.
Group data by kupon and use count function to get the count of particular kupon
select c.kupon,count(*) as count
from kuponbahis c
join bahis b on b.sonuc = c.secim and b.ID=c.bahis AND c.durum=0
group by c.kupon
You need use group by:
select kupon, count(c.id)
from kuponbahis c
join bahis b on b.sonuc = c.secim and b.ID=c.bahis AND c.durum=0
group by 1
Also your origin query looks strange. You use JOIN (wich means INNER JOIN) and don't select any fields from joined table. In this case you can get zero results if your second table has no records to be joined. Maybe you should just remove JOIN statement?
If I understand you requirement correctly, you want to count the number of bahis, but only include rows that has bahis = 24. If so, you can use COUNT and filter the results in the HAVING clause
select c.kupon, count(*) as count
from kuponbahis c
join bahis b
on b.sonuc = c.secim
and b.ID = c.bahis
where
c.durum = 0
group by c.kupon
having count(case when c.bahis = 24 then 1 end) > 0

COUNT evaluate to zero if no matching records

Take the following:
SELECT
Count(a.record_id) AS newrecruits
,a.studyrecord_id
FROM
visits AS a
INNER JOIN
(
SELECT
record_id
, MAX(modtime) AS latest
FROM
visits
GROUP BY
record_id
) AS b
ON (a.record_id = b.record_id) AND (a.modtime = b.latest)
WHERE (((a.visit_type_id)=1))
GROUP BY a.studyrecord_id;
I want to amend the COUNT part to display a zero if there are no records since I assume COUNT will evaluate to Null.
I have tried the following but still get no results:
IIF(ISNULL(COUNT(a.record_id)),0,COUNT(a.record_id)) AS newrecruits
Is this an issue because the join is on record_id? I tried changing the INNER to LEFT but also received no results.
Q
How do I get the above to evaluate to zero if there are no records matching the criteria?
Edit:
To give a little detail to the reasoning.
The studies table contains a field called 'original_recruits' based on activity before use of the database.
The visits tables tracks new_recruits (Count of records for each study).
I combine these in another query (original_recruits + new_recruits)- If there have been no new recruits I still need to display the original_recruits so if there are no records I need it to evalulate to zero instead of null so the final sum still works.
It seems like you want to count records by StudyRecords.
If you need a count of zero when you have no records, you need to join to a table named StudyRecords.
Did you have one? Else this is a nonsense to ask for rows when you don't have rows!
Let's suppose the StudyRecords exists, then the query should look like something like this :
SELECT
Count(a.record_id) AS newrecruits -- a.record_id will be null if there is zero count for a studyrecord, else will contain the id
sr.Id
FROM
visits AS a
INNER JOIN
(
SELECT
record_id
, MAX(modtime) AS latest
FROM
visits
GROUP BY
record_id
) AS b
ON (a.record_id = b.record_id) AND (a.modtime = b.latest)
LEFT OUTER JOIN studyrecord sr
ON sr.Id = a.studyrecord_id
WHERE a.visit_type_id = 1
GROUP BY sr.Id
I solved the problem by amending the final query where I display the result of combining the original and new recruits to include the IIF there.
SELECT
a.*
, IIF(IsNull([totalrecruits]),consents,totalrecruits)/a.target AS prog
, IIf(IsNull([totalrecruits]),consents,totalrecruits) AS trecruits
FROM
q_latest_studies AS a
LEFT JOIN q_totalrecruitment AS b
ON a.studyrecord_id=b.studyrecord_id
;

How to fix a count() in a query with a "group by" clause?

I have a function that gets a SQL code and inserts a count field in it and executes the query to return the number of rows in it. The objective is to have a dynamic SQL code and be able to get its record count no matter what code it has, because I use it in a registry filter window and I never know what code may be generated, because the user can add as many filters as he/she wants.
But as I use the group by clause, the result is wrong because it is counting the number of times a main registry appears because of the use on many join connections.
The result of that code above should only one row with a columns with 10 as result, but I get a new table with the first columns with a 2 in the first row and a 1 on the other rows.
If I take off the group by clause I will receive a 11 as a count result, but the first row will be counted twice.
What should I do to get a single row and the correct number?
SELECT
COUNT(*) QUERYRECORDCOUNT, // this line appears only in the Count() function
ARTISTA.*,
CATEGORIA.NOME AS CATEGORIA,
ATIVIDADE.NOME AS ATIVIDADE,
LOCALIDADE.NOME AS CIDADE,
MATRICULA.NUMERO AS MAP
FROM
ARTISTA
LEFT JOIN PERFIL ON PERFIL.REGISTRO = ARTISTA.ARTISTA_ID
LEFT JOIN CATEGORIA ON CATEGORIA.CATEGORIA_ID = PERFIL.CATEGORIA
LEFT JOIN ATIVIDADE ON ATIVIDADE.ATIVIDADE_ID = PERFIL.ATIVIDADE
LEFT JOIN LOCALIDADE ON LOCALIDADE.LOCALIDADE_ID = ARTISTA.LOCAL_ATIV_CIDADE
LEFT JOIN MATRICULA ON MATRICULA.REGISTRO = ARTISTA.ARTISTA_ID
WHERE
((ARTISTA.SIT_PERFIL <> 'NORMAL') AND (ARTISTA.SIT_PERFIL <> 'PRIVADO'))
GROUP BY
ARTISTA.ARTISTA_ID
ORDER BY
ARTISTA.ARTISTA_ID;
This always gives you the number of rows for any query you have:
Select count(*) as rowcount from
(
Paste your query here
) as countquery
Since your are GROUPING BY ARTISTA.ARTISTA_ID, COUNT(*) QUERYRECORDCOUNT will return records count for each ARTISTA.ARTISTA_ID value.
If you want GLOBAL count, then you need to use a nested query:
SELECT COUNT(*) AS QUERYRECORDCOUNT
FROM (SELECT
ARTISTA.*,
CATEGORIA.NOME AS CATEGORIA,
ATIVIDADE.NOME AS ATIVIDADE,
LOCALIDADE.NOME AS CIDADE,
MATRICULA.NUMERO AS MAP
FROM
ARTISTA
LEFT JOIN PERFIL ON PERFIL.REGISTRO = ARTISTA.ARTISTA_ID
LEFT JOIN CATEGORIA ON CATEGORIA.CATEGORIA_ID = PERFIL.CATEGORIA
LEFT JOIN ATIVIDADE ON ATIVIDADE.ATIVIDADE_ID = PERFIL.ATIVIDADE
LEFT JOIN LOCALIDADE ON LOCALIDADE.LOCALIDADE_ID = ARTISTA.LOCAL_ATIV_CIDADE
LEFT JOIN MATRICULA ON MATRICULA.REGISTRO = ARTISTA.ARTISTA_ID
WHERE
((ARTISTA.SIT_PERFIL <> 'NORMAL') AND (ARTISTA.SIT_PERFIL <> 'PRIVADO'))
GROUP BY
ARTISTA.ARTISTA_ID
ORDER BY
ARTISTA.ARTISTA_ID);
In this case, you may not need to select those many columns.
If you need to retrieve the all records count with details, then better to use two separate queries.

Getting the last 5 records of a joined query

I have a query that does what i want joining table but i need it to change sligtly so i can use it for something else.
I need to get the last 5 records so i should be using the max function and limit it to 5 but it's not working properly
This is my current query, just need to get the last 5 records (probably by the festivalid)
SELECT f.*,
v.total,
v.votes,
v.festivalid,
ifnull(r.reviewcount,0) as count
FROM festivals f
INNER
JOIN vote v
ON f.festivalid = v.festivalid
LEFT OUTER
JOIN (SELECT festivalid,
count(*) as reviewcount
FROM reviews
GROUP BY festivalid) as r
ON r.festivalid = v.festivalid
WHERE f.datefrom > CURRENT_TIMESTAMP
ORDER BY f.datefrom, f.eventname
ORDER BY f.datefrom DESC, f.eventname DESC
Limit 5