I want to have a table where I can view today's balance as well as yesterday's balance as two different column. Is there any way I can select from two different dates?
Below is the SQL statement I have tried however I am not able to see the yesterday balance.
(SELECT food.food_id, food.food_name, food.food_chi_name, food.food_category, food.chinesechar, SUM(inventory.tmr_input+inventory.final_balance), SUM(inventory.balance), SUM(inventory.input), SUM(inventory.reject), SUM(inventory.final_balance), SUM(inventory.tmr_input), SUM(inventory.sale), SUM(inventory.theoritical), SUM(inventory.yest_theoritical), SUM(inventory.3PMsale), SUM(inventory.3PMbalance), SUM(inventory.wholesale) FROM inventory INNER JOIN food ON inventory.food_id=food.food_id WHERE food.outlet = 'T11' AND inventory.date = '04/30/2021' GROUP BY food.food_id ORDER BY food.food_id ASC); (SELECT SUM(inventory.balance) as yesterday_balance FROM inventory INNER JOIN food ON inventory.food_id=food.food_id WHERE food.outlet = 'T11' AND inventory.date = '04/29/2021' GROUP BY food.food_id ORDER BY food.food_id ASC);
You can use a subselect for that purpose
And using aliases helps to get a better overview
SELECT
f1.food_id
, f1.food_name
, f1.food_chi_name
, f1.food_category
, f1.chinesechar
, SUM(i1.tmr_input+i1.final_balance)
, SUM(i1.balance)
, SUM(i1.input)
, SUM(i1.reject)
,SUM(i1.final_balance)
, SUM(i1.tmr_input)
, SUM(i1.sale)
, SUM(i1.theoritical)
, SUM(i1.yest_theoritical)
, SUM(i1.`3PMsale`)
, SUM(i1.`3PMbalance`)
, SUM(i1.wholesale)
,(SELECT SUM(i2.balance)
FROM
inventory i2 INNER JOIN food f2 ON i2.food_id=f2.food_id
WHERE f2.outlet = 'T11' AND i2.date = '04/29/2021'
AND f2.food_id = f1.food_id
) as yesterday_balance
FROM
inventory i1
INNER JOIN
food f1 ON i1.food_id=f1.food_id
WHERE
f1.outlet = 'T11'
AND i1.date = '04/30/2021'
GROUP BY f1.food_id
ORDER BY f1.food_id ASC;
Related
When executing a query statement, the speed is very slow.
SELECT
T1.APPL_SEQ
, T1.COMP_CD
, (SELECT COMP_NM FROM tb_company WHERE COMP_CD = T1.COMP_CD) AS COMP_NM
, T1.GPROD_CD
, (SELECT GPROD_NM FROM tb_gprod WHERE GPROD_CD = T1.GPROD_CD) AS GPROD_NM
, T1.SITE_CD
, (SELECT SITE_NM FROM tb_site WHERE SITE_CD = T1.SITE_CD) AS SITE_NM
, T1.INFLOW_CD
, T1.INFLOW_URL
, T1.STATUS
, T1.REG_DTM
, DECRYPTO(T1.NAME) AS NAME
, DECRYPTO(T1.HP) AS HP
, ifnull(T1.AGE,T1.`115`) AS AGE
, ifnull(T1.GENDER,T1.`116`) AS GENDER
, ifnull(T1.MEMO,T1.`120`) AS MEMO
, ifnull(T1.`105`,T1.`124`) AS TIME
, T1.`125` AS AGE_CHILD
, T2.API_YN
, T2.API_START_DT
, T2.API_END_DT
, T2.API_CD
, T2.DATA_INFLOWCD
, T2.CONFIRM_YN
, T2.SALE_YN
, T2.SALE_PRICE
, T2.BREAKDOWN
, T2.INPUT_DATE
, T3.DIST_YN
, T3.DIST_DT
,(select ifnull((select timestampdiff(DAY, T11.REG_DTM,T1.REG_DTM) AS DIFF2REGTIME from tb_applicant T11 WHERE T11.HP = T1.HP AND T11.GPROD_CD = T1.GPROD_CD AND T11.REG_DTM < T1.REG_DTM order by T11.REG_DTM desc limit 1),-1)) AS HP2_COUNT
FROM
tb_applicant T1
LEFT JOIN mm_applicant T2
ON T1.APPL_SEQ = T2.APPL_SEQ
LEFT JOIN dist_applicant T3
ON T1.APPL_SEQ = T3.APPL_SEQ
LEFT JOIN tb_site T4
ON T4.site_cd = T1.SITE_CD and T4.comp_cd = T1.COMP_CD and T4.gprod_cd = T1.GPROD_CD
WHERE 1=1
AND T1.APPL_SEQ > 147293
AND T4.is_use = 'Y'
$Sql_Search
ORDER BY
$Sql_OrderBy
) U1
, (SELECT #ROWNUM := 0) U2
) V1";
,(select ifnull((...),-1)) AS HP2_COUNT
This is part of why it's so slow.
This query calculates the number of months difference by comparing REG_DTM when the td_applicant table has the same data for HP, GPROD, and COMP.
I don't need to get the date difference, is there any way to improve the query speed?
The main problem are those subselect in the select. As #Akina suggested, you should move them in FROM and make them as join.
They way you have done implies that each subselect is executed for each row returned by the main select.
You have 4 subselect that mean if you have 100 rows you execute 1 (main select) + (4*100) query so 401 instead of 1.
Using join allow the internal optimization engine to choose the best strategy to perform the query, in your way practically no optimization are applied.
I post a short example of how should be your query, didn't refactor the whole query since without database is a bit difficult to do it and I can easily produce a wrong query.
Notice that you select twice on tb_site with different condition, so is up to you to put the correct one.
SELECT T1.APPL_SEQ, T1.COMP_CD, T1.GPROD_CD, T1.SITE_CD
TC.COMP_NM,
TG.GPROD_NM,
TS.SITE_NM,
......
FROM tb_applicant T1
LEFT JOIN mm_applicant T2
JOIN tb_company TC on TC.COMP_CD = T1.COMP_CD
JOIN tb_gprod TG on GPROD_CD = T1.GPROD_CD
JOIN tb_site TS on TS.SITE_CD = T1.SITE_CD ON T1.APPL_SEQ = T2.APPL_SEQ
.......
i have some code to mysql query, but it's not showing right result.
This is my code:
select a.spent
, t_rinci.harga as price
from t_pengajuan
join t_rinci
on t_rinci.id_pengajuan = t_pengajuan.id
left
JOIN
( SELECT t_realisasi.id_rinci as id
, SUM(nilai_realisasi) spent
FROM t_realisasi
GROUP
by id ) a
on a.id = t_rinci.id_rinci
where t_rinci.id_rinci in (a.id)
group
by t_rinci.id_pengajuan
expected result is
spent
price
400000
4250000
1000000
1100000
but it say
spent
price
400000
4250000
1000000
1000000
here my sqlfiddle
Here's an example of a coherent query:
select r.id_pengajuan
, SUM(a.spent) spent
, SUM(r.harga) as price
from t_pengajuan p
join t_rinci r
on r.id_pengajuan = p.id
JOIN
( SELECT t_realisasi.id_rinci as id
, SUM(nilai_realisasi) spent
FROM t_realisasi
GROUP
by id ) a
on a.id = r.id_rinci
group
by r.id_pengajuan
It might not be what you're after, but it does at least make sense.
I have three tables employee, promotion and punishment
Employee’s table structure something like this
Id int
Fullname varchar
...............
promotionDate date
Promotion’s table structure is like this
id int
emp_id int
directorateDate date
And punishment’s table structure is like this
id int
emp_id int
direcotorateDate date
Let’s say employee table has 200 records, each month a group of employees have promotion (after serving one year), I want to get the list of all employees in the current month that get promotion
I can easily get the list by this query
SELECT *
FROM employee
WHERE MONTH(promotionDate) = MONTH(CURRENT_DATE())
AND YEAR(promotionDate) = YEAR(CURRENT_DATE())
My question is
I want to count number of punishments and promotions each employee got in the current year from punishment and promotion table respectively
I did this query but it did not get right results
SELECT e.fullname , COUNT(punish.emp_id) as siza ,COUNT(pro.emp_id) as supas
FROM emp_employee as e
LEFT JOIN emp_punishment as punish on punish.emp_id=e.id
LEFT JOIN emp_promotion as pro on e.id=pro.emp_id
WHERE ((MONTH(e.promotionDate) = MONTH(CURRENT_DATE())
AND YEAR(e.promotionDate) = YEAR(CURRENT_DATE()))
AND ( YEAR(punish.directorate_date) = YEAR(CURRENT_DATE()) )
AND ( YEAR(pro.directorate_date) = YEAR(CURRENT_DATE()) )
GROUP BY e.fullname;
Any help please.
By joining directly the 3 tables you get duplicate rows.
Group by emp_id and aggregate separately each of the tables emp_punishment and emp_promotion and join the results to the table emp_employee.
select e.fullname, coalesce(pu.siza, 0) siza, coalesce(pr.supas, 0) supas
from emp_employee as e
left join (
select emp_id, count(*) siza
from emp_punishment
where year(directorate_date) = year(CURRENT_DATE)
group by emp_id
) pu on pu.emp_id = e.id
left join (
select emp_id, count(*) supas
from emp_promotion
where year(directorate_date) = year(CURRENT_DATE)
group by emp_id
) pr on pr.emp_id = e.id
I used only the condition:
where year(directorate_date) = year(CURRENT_DATE())
because in your question you say:
I want to count number of punishments and promotions each employee got in the current year from punishment and promotion
Removing MONTH() function, and moving each condition to their respective place, instead of within the WHERE clause should resolve the issue (Since, they're considered as if INNER JOINs with the current style ).
Only keep common column e.promotionDate within the WHERE clause :
SELECT e.fullname,
COUNT(punish.emp_id) as siza ,
COUNT(pro.emp_id) as supas
FROM emp_employee as e
LEFT JOIN emp_punishment as punish
ON punish.emp_id=e.id
AND YEAR(punish.directorate_date) = YEAR(CURRENT_DATE())
LEFT JOIN emp_promotion as pro
ON e.id=pro.emp_id
AND YEAR(pro.directorate_date) = YEAR(CURRENT_DATE()))
WHERE YEAR(e.promotionDate) = YEAR(CURRENT_DATE())
GROUP BY e.fullname;
Basically below query now works in order to retrieve what I want.
But I'm pretty sure there is a more efficient way to write this query:
SELECT dg.ultimo_codigo_de_gestion_prejuridico, dg.hora_inicio_gestion,
dg.telefono, dg.fecha_gestion, cg.valor_codigo, cg.contacto
FROM detalle_gestion_con_obligacion
AS dg INNER JOIN codigo_gestion
AS cg ON dg.ultimo_codigo_de_gestion_prejuridico = cg.cod_gestion
WHERE nro_documento = 1234567
AND DATE(fecha_gestion) NOT IN (2018-10-20) AND telefono
IN ((SELECT tel_residencia FROM obligacion WHERE nro_obligacion = 1234567) ,
(SELECT tel_oficina FROM obligacion WHERE nro_obligacion = 1234567),
(SELECT celular FROM obligacion WHERE nro_obligacion = 1234567),
(SELECT tel_residencia1 FROM obligacion WHERE nro_obligacion = 1234567) )
ORDER BY fecha_gestion DESC, hora_inicio_gestion DESC limit 1;
As you might tell, around the IN clause I want to retrieve agreements (detalle_gestion_con_obligacion) where the telephone belongs to that list.
I am looking for a better solution that doesn't need four different SELECT statements.
You can join with obligacion instead of using IN.
SELECT dg.ultimo_codigo_de_gestion_prejuridico, dg.hora_inicio_gestion,
dg.telefono, dg.fecha_gestion, cg.valor_codigo, cg.contacto
FROM detalle_gestion_con_obligacion AS dg
INNER JOIN codigo_gestion AS cg ON dg.ultimo_codigo_de_gestion_prejuridico = cg.cod_gestion
INNER JOIN obligacion AS o ON telefono IN (o.tel_residencia, o.yel_oficina, o.celular, o.tel_residencial)
WHERE nro_documento = 1234567
AND DATE(fecha_gestion) NOT IN (2018-10-20)
ORDER BY fecha_gestion DESC, hora_inicio_gestion DESC
limit 1;
I have a MYSQL query I'm working on that pulls data from multiple joins.
select students.studentID, students.firstName, students.lastName, userAccounts.userID, userstudentrelationship.userID, userstudentrelationship.studentID, userAccounts.getTexts, reports.pupID, contacts.pfirstName, contacts.plastName, reports.timestamp
from userstudentrelationship
join userAccounts on (userstudentrelationship.userID = userAccounts.userID)
join students on (userstudentrelationship.studentID = students.studentID)
join reports on (students.studentID = reports.studentID)
join contacts on (reports.pupID = contacts.pupID)
where userstudentrelationship.studentID = "10000005" AND userAccounts.getTexts = 1 ORDER BY reports.timestamp DESC LIMIT 1
I have a unique situation where I would like one of the joins (the reports join) to be limited to the latest result only for that table (order by reports.timestamp desc limit 1 is what I use), while not limiting the result quantities for the overall query.
By running the above query I get the data I would expect, but only one record when it should return several.
My question:
How can I modify this query to ensure that I receive all possible records available, while ensuring that only the latest record from the reports join used? I expect that each record will possibly contain different data from the other joins, but all records returned by this query will share the same report record
Provided I understand the issue; one could add a join to a set of data (aliased Z below) that has the max timestamp for each student; thereby limiting to one report record (most recent) for each student.
SELECT students.studentID
, students.firstName
, students.lastName
, userAccounts.userID
, userstudentrelationship.userID
, userstudentrelationship.studentID
, userAccounts.getTexts
, reports.pupID
, contacts.pfirstName
, contacts.plastName
, reports.timestamp
FROM userstudentrelationship
join userAccounts
on userstudentrelationship.userID = userAccounts.userID
join students
on userstudentrelationship.studentID = students.studentID
join reports
on students.studentID = reports.studentID
join contacts
on reports.pupID = contacts.pupID
join (SELECT max(timestamp) mts, studentID
FROM REPORTS
GROUP BY StudentID) Z
on reports.studentID = Z.studentID
and reports.timestamp = Z.mts
WHERE userstudentrelationship.studentID = "10000005"
AND userAccounts.getTexts = 1
ORDER BY reports.timestamp
for get all the records you should avoid limit 1 at the end of the query
for join anly one row from reports table you could use subquery as
select
students.studentID
, students.firstName
, students.lastName
, userAccounts.userID
, userstudentrelationship.userID
, userstudentrelationship.studentID
, userAccounts.getTexts
, t.pupID
, contacts.pfirstName
, contacts.plastName
, t.timestamp
from userstudentrelationship
join userAccounts on userstudentrelationship.userID = userAccounts.userID
join students on userstudentrelationship.studentID = students.studentID
join (
select * from reports
order by reports.timestamp limit 1
) t on students.studentID = t.studentID
join contacts on reports.pupID = contacts.pupID
where userstudentrelationship.studentID = "10000005"
AND userAccounts.getTexts = 1