How to Add and Compare Results from Subqueries - mysql

I have the following code written for a larger report that I have been working on. I have three columns resulting from subqueries: req_hrs, e_hrs, inprog_hrs. I need to add together the e_hrs and inprog_hrs, thus seeing whether that number is greater than or equal to req_hrs. If that is true, I need to return either an * or a null value.
Can someone please explain to me how I can add the two subquery results (e_hrs and inprog_hrs) together, and then compare that result to req_hrs thus returning said * or NVL? Code is below, Thank you:
SELECT
spriden_last_name lname,
spriden_first_name fname,
spriden_mi mi,
spriden_id id,
x.shrdgmr_majr_code_1 majr,
x.shrdgmr_grad_date grad_dt,
x.shrdgmr_degs_code degs,
DECODE(stvdegs_award_status_ind,'A','*',NULL) award_ind,
**DECODE(NVL(m.smbagen_req_credits_overall,0),0,
DECODE(NVL(sorcmjr_req_hours_ssdf,0),0,
DECODE(stvdegc_acat_code,'22',32,'23',64,'24',124,'42',42,999),
sorcmjr_req_hours_ssdf),m.smbagen_req_credits_overall) req_hrs,**
**TRUNC(shrlgpa_hours_earned,2) AS e_hrs,**
**(SELECT
NVL(SUM(sfrstcr_credit_hr),0)
FROM
sfrstcr
WHERE
sfrstcr_term_code = '&inprog_term'
AND sfrstcr_pidm = x.shrdgmr_pidm
AND sfrstcr_rsts_code IN ('RE','RW')
AND NOT EXISTS (
SELECT
'Y'
FROM
shrtckn,
shrtckg j
WHERE
shrtckn_pidm = sfrstcr_pidm
AND shrtckn_term_code = sfrstcr_term_code
AND shrtckn_crn = sfrstcr_crn
AND j.shrtckg_pidm = shrtckn_pidm
AND j.shrtckg_term_code = shrtckn_term_code
AND j.shrtckg_tckn_seq_no = shrtckn_seq_no
AND j.shrtckg_seq_no = (
SELECT
MAX(k.shrtckg_seq_no)
FROM
shrtckg k
WHERE
k.shrtckg_pidm = shrtckn_pidm
AND k.shrtckg_term_code = shrtckn_term_code
AND k.shrtckg_tckn_seq_no = shrtckn_seq_no))) AS inprog_hrs,**
ROUND(shrlgpa_gpa,2) gpa,
DECODE(SIGN(shrlgpa_gpa - 3.90),0,'S',1,'S',
DECODE(SIGN(shrlgpa_gpa - 3.75),0,'M',1,'M',
DECODE(SIGN(shrlgpa_gpa - 3.50),0,'C',1,'C',NULL))) latin,
(SELECT
m.shrasdl_astd_code_dl
FROM
shrasdl m
WHERE
m.shrasdl_term_code_effective = (
SELECT
MAX(n.shrasdl_term_code_effective)
FROM
shrasdl n)
AND m.shrasdl_min_gpa_term = (
SELECT
MAX(n.shrasdl_min_gpa_term)
FROM
shrasdl n
WHERE
n.shrasdl_term_code_effective = m.shrasdl_term_code_effective
AND shrlgpa_gpa >= n.shrasdl_min_gpa_term)) honors
FROM
shrdgmr x,
stvdegs,
stvdegc,
spriden,
sorcmjr,
smbagen m,
shrlgpa
WHERE
TO_CHAR(x.shrdgmr_grad_date,'MON-YY') IN ('&grad_dt1', NVL('&grad_dt2','XXX-
00'))
AND x.shrdgmr_seq_no = (
SELECT
MAX(z.shrdgmr_seq_no)
FROM
shrdgmr z
WHERE
z.shrdgmr_pidm = x.shrdgmr_pidm
AND z.shrdgmr_majr_code_1 = x.shrdgmr_majr_code_1
AND z.shrdgmr_grad_date IS NOT NULL)
AND stvdegs_code = x.shrdgmr_degs_code
AND stvdegc_code = x.shrdgmr_degc_code
AND spriden_pidm = x.shrdgmr_pidm
AND spriden_change_ind IS NULL
AND sorcmjr_cmjr_rule(+) = x.shrdgmr_cmjr_rule_1_1
AND REPLACE(m.smbagen_area(+),'-CORE','') = x.shrdgmr_majr_code_1
AND m.smbagen_active_ind(+) = 'Y'
AND m.smbagen_term_code_eff(+) <= x.shrdgmr_term_code_grad
AND ((m.smbagen_area IS NULL)
OR (m.smbagen_area IS NOT NULL
AND m.smbagen_term_code_eff = (
SELECT
MAX(n.smbagen_term_code_eff)
FROM
smbagen n
WHERE
REPLACE(n.smbagen_area,'-CORE','') = x.shrdgmr_majr_code_1
AND n.smbagen_active_ind = 'Y'
AND n.smbagen_term_code_eff <= x.shrdgmr_term_code_grad)))
AND shrlgpa_pidm(+) = x.shrdgmr_pidm
AND shrlgpa_levl_code(+) = x.shrdgmr_levl_code
AND shrlgpa_gpa_type_ind(+) = 'O'
ORDER BY
spriden_last_name,
spriden_first_name,
spriden_mi
;

Compare the sum of the union of the two sources with the required amount.
In simplified form:
select somekey, sum(hrs) worked_hrs, sum(req_hrs) required_hrs
from (
select
somekey,
e_hrs hrs
from e_hrs_table
where ...
union all -- the "all" is important to leave in!
select
somekey,
inprog_hrs
from inprog_hrs_table
where ...
) x
join req_hrs_table on req_hrs_table.somekey = x.somekey
where ... -- add req_hrs_table conditions here
group by somekey
You can add
having sum(hrs) < sum(req_hrs)
if you want only those rows that did not meet the quota.

Related

How to get records that match value or exist in another table?

I am trying to figure out how to get all tasks in this case that two of the fields equal a certain value or they exist in the other table?
Here is the query:
SELECT TASKS.task_id, TASKS.task_title, TASKS.task_description, TASKS.task_assigned_name, TASKS.task_assigned_phone_number, TASKS.task_due_date_time, TASKS.task_category
FROM TASKS
WHERE TASKS.task_complete = 1 AND
(TASKS.task_creator_id = ? OR
TASKS.task_assigned_user_id = ? OR
WHERE EXISTS (SELECT WATCHERS.task_id
FROM WATCHERS
WHERE WATCHERS.task_id = TASK.task_id AND
WATCHERS.watcher_user_id = ?
)
);
This is not returning anything even though I am expecting a result from my db.
You seem to have an error in your syntax. You have too many WHEREs:
SELECT t.task_id, t.task_title, t.task_description, t.task_assigned_name, t.task_assigned_phone_number, t.task_due_date_time, t.task_category
FROM TASKS t
WHERE t.task_complete = 1 AND
(t.task_creator_id = ? OR
t.task_assigned_user_id = ? OR
EXISTS (SELECT 1 -- the return value is immaterial
FROM WATCHERS w
WHERE w.task_id = t.task_id AND
w.watcher_user_id = ?
)
);
The WHERE before EXISTS is not appropriate.
Your query should be returning an error. Be sure to check for errors!
Have you tried using a join?
SELECT TASKS.task_id,
TASKS.task_title,
TASKS.task_description,
TASKS.task_assigned_name,
TASKS.task_assigned_phone_number,
TASKS.task_due_date_time,
TASKS.task_category
FROM TASKS
JOIN WATCHERS on WATCHERS.task_id = TASK.task_id
WHERE TASKS.task_complete = 1 AND
(TASKS.task_creator_id = ? OR
TASKS.task_assigned_user_id = ? OR
WATCHERS.watcher_user_id = ?);
I'm not sure if that's the logic you are looking for.
besides the extra where in your query, looks like you may have an extra closed parenthesis.
This sql matches the result set you posted in your duplicate post that has sample data and result:
SELECT t.task_id, t.task_complete, t.task_creator_id, t.task_assigned_user_Id
FROM tasks t
WHERE t.task_complete = 1 AND
(
t.task_creator_id = 8
OR t.task_assigned_user_id = 8
OR EXISTS
(
SELECT w.task_id
FROM watchers w
WHERE w.task_id = t.task_id
AND w.watcher_user_id = 8
)
)

Need records from one table if value matches or if value exists in another table [duplicate]

I am trying to figure out how to get all tasks in this case that two of the fields equal a certain value or they exist in the other table?
Here is the query:
SELECT TASKS.task_id, TASKS.task_title, TASKS.task_description, TASKS.task_assigned_name, TASKS.task_assigned_phone_number, TASKS.task_due_date_time, TASKS.task_category
FROM TASKS
WHERE TASKS.task_complete = 1 AND
(TASKS.task_creator_id = ? OR
TASKS.task_assigned_user_id = ? OR
WHERE EXISTS (SELECT WATCHERS.task_id
FROM WATCHERS
WHERE WATCHERS.task_id = TASK.task_id AND
WATCHERS.watcher_user_id = ?
)
);
This is not returning anything even though I am expecting a result from my db.
You seem to have an error in your syntax. You have too many WHEREs:
SELECT t.task_id, t.task_title, t.task_description, t.task_assigned_name, t.task_assigned_phone_number, t.task_due_date_time, t.task_category
FROM TASKS t
WHERE t.task_complete = 1 AND
(t.task_creator_id = ? OR
t.task_assigned_user_id = ? OR
EXISTS (SELECT 1 -- the return value is immaterial
FROM WATCHERS w
WHERE w.task_id = t.task_id AND
w.watcher_user_id = ?
)
);
The WHERE before EXISTS is not appropriate.
Your query should be returning an error. Be sure to check for errors!
Have you tried using a join?
SELECT TASKS.task_id,
TASKS.task_title,
TASKS.task_description,
TASKS.task_assigned_name,
TASKS.task_assigned_phone_number,
TASKS.task_due_date_time,
TASKS.task_category
FROM TASKS
JOIN WATCHERS on WATCHERS.task_id = TASK.task_id
WHERE TASKS.task_complete = 1 AND
(TASKS.task_creator_id = ? OR
TASKS.task_assigned_user_id = ? OR
WATCHERS.watcher_user_id = ?);
I'm not sure if that's the logic you are looking for.
besides the extra where in your query, looks like you may have an extra closed parenthesis.
This sql matches the result set you posted in your duplicate post that has sample data and result:
SELECT t.task_id, t.task_complete, t.task_creator_id, t.task_assigned_user_Id
FROM tasks t
WHERE t.task_complete = 1 AND
(
t.task_creator_id = 8
OR t.task_assigned_user_id = 8
OR EXISTS
(
SELECT w.task_id
FROM watchers w
WHERE w.task_id = t.task_id
AND w.watcher_user_id = 8
)
)

Joining different WHERE clauses on mySQL multiple select statement

As someone who constantly has problems with databases, I'm trying to look for a solution that optimizes my database calls. Scenario is this, I'm trying to get all rows of items directly owned by the user, but also I want to get the rows of items where the user roles acts as a guest. My current query works, but I think it isn't the best forged solution for what I'm trying to achieve. This get me the results I want, but I fear when there are hundreds of rows this will get terribly slow
set #UsrId = 23;
(SELECT Eventos.Fecha, Eventos.InformacionDelEvento, Eventos.PosicionGpsSiNo, Eventos.InformacionGps, Dispositivos.Nombre, CatalogoDeEventos.Descripcion
FROM Eventos, CatalogoDeEventos, Dispositivos, DispositivosxUsuario
WHERE Eventos.IdEvento = CatalogoDeEventos.Id
AND Dispositivos.IdentificadorUnico = Eventos.IdDispositivo
AND DispositivosxUsuario.IdDispositivo = Dispositivos.Id
AND Dispositivos.Invisible = 0
AND DispositivosxUsuario.IdUsuario = #UsrId
ORDER BY Fecha DESC)
UNION
(SELECT Eventos.Fecha, Eventos.InformacionDelEvento, Eventos.PosicionGpsSiNo, Eventos.InformacionGps, Dispositivos.Nombre, CatalogoDeEventos.Descripcion
FROM Eventos, CatalogoDeEventos, Dispositivos, DispositivosxUsuario, Seguidores
WHERE Eventos.IdEvento = CatalogoDeEventos.Id
AND Dispositivos.IdentificadorUnico = Eventos.IdDispositivo
AND DispositivosxUsuario.IdDispositivo = Dispositivos.Id
AND Dispositivos.Invisible = 0
AND Seguidores.IdUsuario = DispositivosxUsuario.IdUsuario
AND Seguidores.IdSeguidor = #UsrId
ORDER BY Fecha DESC)
So both queries have this same block
SELECT Eventos.Fecha, Eventos.InformacionDelEvento, Eventos.PosicionGpsSiNo, Eventos.InformacionGps, Dispositivos.Nombre, CatalogoDeEventos.Descripcion
FROM Eventos, CatalogoDeEventos, Dispositivos, DispositivosxUsuario
WHERE Eventos.IdEvento = CatalogoDeEventos.Id
AND Dispositivos.IdentificadorUnico = Eventos.IdDispositivo
AND DispositivosxUsuario.IdDispositivo = Dispositivos.Id
AND Dispositivos.Invisible = 0
They differ on the lines above this, so far I haven't figured a way of getting both results on a single call
this should work
SELECT Eventos.Fecha, Eventos.InformacionDelEvento, Eventos.PosicionGpsSiNo, Eventos.InformacionGps, Dispositivos.Nombre, CatalogoDeEventos.Descripcion
FROM Eventos, CatalogoDeEventos, Dispositivos, DispositivosxUsuario, Seguidores
WHERE Eventos.IdEvento = CatalogoDeEventos.Id
AND Dispositivos.IdentificadorUnico = Eventos.IdDispositivo
AND DispositivosxUsuario.IdDispositivo = Dispositivos.Id
AND Dispositivos.Invisible = 0
AND Seguidores.IdUsuario = DispositivosxUsuario.IdUsuario
AND (
(Seguidores.IdUsuario = DispositivosxUsuario.IdUsuario
AND Seguidores.IdSeguidor = #UsrId)
OR DispositivosxUsuario.IdUsuario = #UsrId)
ORDER BY Fecha DESC
as was mentioned in the comments, this effectively left joins on Sequidores and that would probably have been more obvious if the query was written with the newer join syntax.
Re-written to use newer join syntax
SELECT e.Fecha, e.InformacionDelEvento, e.PosicionGpsSiNo, e.InformacionGps, d.Nombre, cde.Descripcion
FROM Eventos e
INNER JOIN CatalogoDeEventos cde ON e.IdEvento = cde.Id
INNER JOIN Dispositivos d ON d.IdentificadorUnico = e.IdDispositivo
INNER JOIN DispositivosxUsuario du ON du.IdDispositivo = d.Id
LEFT JOIN Seguidores s ON s.IdUsuario = du.IdUsuario
WHERE d.Invisible = 0
AND (Seguidores.IdSeguidor = #UsrId
OR DispositivosxUsuario.IdUsuario = #UsrId)
ORDER BY Fecha DESC

how to perform count using nested select in a select statement

So here is the issue. I'm trying to write a new fillrate report because the one built in is not good enough... I'm trying to run a single select statement to return both, a count of how many times an item was ordered for a specific month, and then also a count of how many times it was invoiced/shipped in full.
This code is obviously wrong, I also currently have it restricted to only look at AUG of 2015, but that is just to simplify results during testing.
I can't figure out how to do the 2nd count... This is what I was trying (brain stuck on old for each loop logic):
select inv_mast.item_id,
inv_mast.item_desc,
"YEAR" = year(oe_line.required_date),
"MONTH" = month(oe_line.required_date),
"ORDERS" = count(1),
"HITS" = (
select count(1)
from invoice_line
where invoice_line.order_no = oe_line.order_no
and invoice_line.oe_line_number = oe_line.line_no
and invoice_line.qty_shipped = oe_line.qty_ordered
)
from oe_line,
inv_mast,
inv_loc
where inv_mast.inv_mast_uid = oe_line.inv_mast_uid
and inv_mast.delete_flag = 'N'
and inv_mast.inv_mast_uid = inv_loc.inv_mast_uid
and inv_loc.location_id = '101'
and year(oe_line.required_date) = '2015'
and month(oe_line.required_date) = '8'
group by inv_mast.item_id,
inv_mast.item_desc,
year(oe_line.required_date),
month(oe_line.required_date)
order by inv_mast.item_id
To me it would seem like you could rewrite the query to use a left join on the invoice_line table instead. Without any proper test data I can't guarantee it is correct, but I think it should be.
Besides the left join I also changed to explicit joins and moved the aliases as I don't think MySQL supports the alias = column syntax.
select inv_mast.item_id,
inv_mast.item_desc,
year(o.required_date) as "YEAR",
month(o.required_date) as "MONTH",
count(1) as "ORDERS",
count(invoice_line.order_no) as "HITS"
from oe_line o
join inv_mast on inv_mast.inv_mast_uid = o.inv_mast_uid
join inv_loc on inv_mast.inv_mast_uid = inv_loc.inv_mast_uid
left join invoice_line on invoice_line.order_no = o.order_no
and invoice_line.oe_line_number = o.line_no
and invoice_line.qty_shipped = o.qty_ordered
where inv_mast.delete_flag = 'N'
and inv_loc.location_id = '101'
and year(o.required_date) = '2015'
and month(o.required_date) = '8'
group by inv_mast.item_id,
inv_mast.item_desc,
year(o.required_date),
month(o.required_date)
order by inv_mast.item_id;

MySql Rolling sum issue

I want to do rolling sum of column. I have created following query
SET #FinancialIncremental:=0;
SELECT j.ErrorCategory,
COUNT(IF(j.ErrorType = 'P',j.ErrorType,NULL)) AS Financial,
COUNT(IF(j.ErrorType = 'NP',j.ErrorType,NULL)) AS Procedural,
SUM(j.OverPaymentAmount) AS 'Financial Over Paid Amount ($)',
(
SELECT
#FinancialIncremental := #FinancialIncremental + q1.c
FROM
(
(SELECT
COUNT(IF(ErrorType = 'P',ErrorType,NULL)) AS c
FROM DemoScheme.TestTable WHERE IsDeleted = 0 AND ErrorType IN ('P','NP')
GROUP BY ErrorCategory) AS q1
)
) AS 'Financial Incremental'
FROM DemoScheme.TestTable j WHERE IsDeleted = 0 AND ErrorType IN ('P','NP')
GROUP BY ErrorCategory;
But It is giving me an error. It giving me an error on 'Financial Incremental' subquery
Error Code: 1242. Subquery returns more than 1 row
Can anybody help me to solve this?
You have some repetitions in there which complicate things unnecessarily,try this query.You might also need to replace NULL with 0 when you add it.
SET #FinancialIncremental:=0;
SELECT j.ErrorCategory,
COUNT(IF(j.ErrorType = 'P',j.ErrorType,NULL)) AS Financial,
COUNT(IF(j.ErrorType = 'NP',j.ErrorType,NULL)) AS Procedural,
SUM(j.OverPaymentAmount) AS 'Financial Over Paid Amount ($)',
(#FinancialIncremental := #FinancialIncremental + COUNT(IF(j.ErrorType = 'P',j.ErrorType,0))
AS 'Financial Incremental'
FROM DemoScheme.TestTable j WHERE IsDeleted = 0 AND ErrorType IN ('P','NP')
GROUP BY ErrorCategory;