sql query group by not working in subquery - mysql

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.

Related

SQL Aggregate with join giving incorrect results

In a bid to learn SQL i've added some dummy data into a few tables that i generated in Excel. I've got a table for customer, order headers and order lines.
Im trying to check that the customers balance, order header total and line totals all match.
But when I run this query I get the incorrect output for the orderheader, i believe it to be becuase its doing the SUM for the amount of times the orderlines table is referenced.
Can anyone tell me the correct way i should be doing it?
SELECT
cus.cus_id,
cus.cus_name,
cus.cus_balance,
SUM(orderheader.orderheader_currentsell) AS orderHeader_total,
SUM(orderlines.orderlines_currentsell) AS orderLines_total
FROM
cus
JOIN
orderheader ON orderheader.orderHeader_customer = cus.cus_id
JOIN
orderlines ON orderlines.orderlines_orderid = orderheader.orderHeader_id
GROUP BY cus.cus_name
output ( the highlighted column should be the same as the other values.)
You have multiple rows for the header. To solve this, aggregate before doing the join. In your case, just aggregating the order lines should be sufficient:
SELECT c.cus_id, c.cus_name, c.cus_balance,
SUM(oh.orderheader_currentsell) AS orderHeader_total,
SUM(ol.orderLines_total) AS orderLines_total
FROM cus c JOIN
orderheader oh
ON oh.orderHeader_customer = c.cus_id JOIN
(SELECT ol.orderlines_orderid, SUM((ol.orderlines_currentsell) as orderLines_total
FROM orderlines ol
GROUP BY ol.orderlines_orderid
) ol
ON ol.orderlines_orderid = oh.orderHeader_id
GROUP BY cus.cus_name;
Because you have different levels of grouping, it's not that trivial, and you need subselects.
You can calculate the total per customer as a subselect in the field list. In the code below I've done that just for the orders, but you could do the same for the order lines which are still solved by the grouping.
SELECT
cus.cus_id,
cus.cus_name,
cus.cus_balance,
( SELECT
SUM(orderheader_currentsell)
FROM
orderheader
WHERE
orderheader.orderHeader_customer = cus.cus_id) AS orderHeader_total,
SUM(orderlines.orderlines_currentsell) AS orderLines_total
FROM
cus
JOIN
orderlines ON orderlines.orderlines_orderid = orderheader.orderHeader_id
GROUP BY cus.cus_name
This is at first glance, but I am noticing you have:
cus.cus_id,
cus.cus_name,
cus.cus_balance,
as the non-aggregate columns. But in your Group-By you only have:
GROUP BY cus.cus_name
Group By should include all of the non-aggregate columns. This may be why you're not getting the expected results. That would be changed to:
GROUP BY cus.cus_id,
cus.cus_name,
cus.cus_balance

what will be correct MySql query?

I am performing the following query having some syntax error:
SELECT count (tbl_staff.staff_id as staff_number),SELECT count (tbl_client.client_id as client_number),SELECT count (tbl_appointment.appt_id as appt_number),SELECT count (tbl_subscription.subscription_id as subscription_number)
FROM tbl_subscription
LEFT JOIN tbl_staff
ON (
tbl_staff.merchant_id = tbl_subscription.merchant_id)
LEFT JOIN tbl_appointment
ON (
tbl_appointment.merchant_id = tbl_subscription.merchant_id)
LEFT JOIN tbl_client
ON (
tbl_client.merchant_id = tbl_subscription.merchant_id)
WHERE tbl_subscription.subscription_id=1;
I want get the count of staff_id, client_d, appointment_id on particular Subscription_id.
Your select list is close, but has a few mistakes. Namely, you only need a single SELECT in your query (not one per field) and the "as ..." descriptor belongs outside the parenthesis.
So this part of the query
SELECT count (tbl_staff.staff_id as staff_number),
SELECT count (tbl_client.client_id as client_number),
SELECT count (tbl_appointment.appt_id as appt_number),
SELECT count (tbl_subscription.subscription_id as subscription_number)
FROM tbl_subscription
would become
SELECT count (tbl_staff.staff_id) as staff_number,
count (tbl_client.client_id) as client_number,
count (tbl_appointment.appt_id) as appt_number,
count (tbl_subscription.subscription_id) as subscription_number
FROM tbl_subscription

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