MYSQL | Getting syntax error for using subquery in COUNT() - mysql

SELECT
E.`employee_id`,
E.`full_name`,
LE.`no_of_leaves` AS AllocatedLeaves,
MLLT.`leave_type` AS LeaveTypeName,
COUNT(SELECT * FROM leave_approval WHERE employee_id = 1) AS TotalLeavesTaken
FROM employee E
INNER JOIN leave_entitlement LE
ON E.`employee_id` = LE.`employee_id`
INNER JOIN `ml_leave_type` MLLT
ON MLLT.`ml_leave_type_id` = LE.`ml_leave_type_id`
LEFT JOIN leave_approval LA
ON E.`employee_id` = LA.`employee_id`
LEFT JOIN leave_application LAPP
ON LAPP.`application_id` = LA.`leave_application_id`
LEFT JOIN ml_leave_type MLLTLA
ON MLLTLA.`ml_leave_type_id` = LAPP.`ml_leave_type_id`
i am getting syntax error near count, but i tried to find out the syntax error and i could not find any?
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select * from leave_approval where employee_id = 1) AS TotalLeavesTaken
from emp' at line 6
Is it really a syntax error. or is there something i am missing here??

This line:
COUNT(SELECT * FROM leave_approval WHERE employee_id = 1) AS TotalLeavesTaken
is incorrect. You can not do a count on select * subquery without placing it in parentheses, but even then you'd need a group by and additional logic. The better approach would be:
(Select count(*) from leave_approval where employee_id = 1) AS TotalLeavesTaken

change
COUNT(SELECT * FROM leave_approval WHERE employee_id = 1) AS TotalLeavesTaken
to
(SELECT count(*) FROM leave_approval WHERE employee_id = 1) AS TotalLeavesTaken

No need to use subquery for count in your case check below query
Try this:
SELECT E.employee_id, E.full_name, LE.no_of_leaves AS AllocatedLeaves,
MLLT.leave_type AS LeaveTypeName,
SUM(CASE WHEN LA.employee_id = 1 THEN 1 ELSE 0 END) AS TotalLeavesTakenByEmplyeeNo1
FROM employee E
INNER JOIN leave_entitlement LE ON E.employee_id = LE.employee_id
INNER JOIN `ml_leave_type` MLLT ON MLLT.ml_leave_type_id = LE.ml_leave_type_id
LEFT JOIN leave_approval LA ON E.employee_id = LA.employee_id
LEFT JOIN leave_application LAPP ON LAPP.application_id = LA.leave_application_id
LEFT JOIN ml_leave_type MLLTLA ON MLLTLA.ml_leave_type_id = LAPP.ml_leave_type_id
GROUP BY E.employee_id;

Try This Query
SELECT E.`employee_id`,E.`full_name`,LE.`no_of_leaves` AS AllocatedLeaves,MLLT.`leave_type` AS LeaveTypeName,
SUM( CASE WHEN LA.employee_id = '1' THEN 1 ELSE 0 END ) as TotalLeavesTaken
FROM employee E
INNER JOIN leave_entitlement LE
ON E.`employee_id` = LE.`employee_id`
INNER JOIN `ml_leave_type` MLLT
ON MLLT.`ml_leave_type_id` = LE.`ml_leave_type_id`
LEFT JOIN leave_approval LA
ON E.`employee_id` = LA.`employee_id`
LEFT JOIN leave_application LAPP
ON LAPP.`application_id` = LA.`leave_application_id`
LEFT JOIN ml_leave_type MLLTLA
ON MLLTLA.`ml_leave_type_id` = LAPP.`ml_leave_type_id`
Only you have to replace COUNT(SELECT * FROM leave_approval WHERE employee_id = 1) to SUM( CASE WHEN LA.employee_id = '1' THEN 1 ELSE 0 END )
Thanks it, Try this because i have tried this query and it will give you perfect result

Related

How to efficiently select the rows corresponding with the highest value for a specific column?

I have a query:
SELECT * FROM `InvoiceLines`
INNER JOIN Invoices ON Invoices.`invoiceID` = InvoiceLines.`invoiceID`
INNER JOIN `DistributorOrdersTbl` ON DistributorOrdersTbl.`distOrderRecID` = Invoices.`orderID`
WHERE DistributorOrdersTbl.`distOrderRecID` = 3829
AND InvoiceLines.`qty` > 0
Which returns a number of Invoices:
I wanted to select only the invoices with the newest ID 2800. The way I ended up doing it was a bit of copy pasting:
SELECT * FROM `InvoiceLines`
INNER JOIN Invoices ON Invoices.`invoiceID` = InvoiceLines.`invoiceID`
INNER JOIN `DistributorOrdersTbl` ON DistributorOrdersTbl.`distOrderRecID` = Invoices.`orderID`
WHERE DistributorOrdersTbl.`distOrderRecID` = 3829
AND InvoiceLines.`qty` > 0
AND Invoices.invoiceID = (
SELECT MAX(Invoices.invoiceID) FROM `InvoiceLines`
INNER JOIN Invoices ON Invoices.`invoiceID` = InvoiceLines.`invoiceID`
INNER JOIN `DistributorOrdersTbl` ON DistributorOrdersTbl.`distOrderRecID` = Invoices.`orderID`
WHERE DistributorOrdersTbl.`distOrderRecID` = 3829
AND InvoiceLines.`qty` > 0
)
And sure enough, the correct invoices are returned. However it feels as though this is inefficient as I am essentially performing the query twice. What would be the best way of doing this? I tried the following but it seems this is incorrect SQL:
SELECT * FROM `InvoiceLines`
INNER JOIN Invoices ON Invoices.`invoiceID` = InvoiceLines.`invoiceID`
INNER JOIN `DistributorOrdersTbl` ON DistributorOrdersTbl.`distOrderRecID` = Invoices.`orderID`
WHERE DistributorOrdersTbl.`distOrderRecID` = 3829
AND InvoiceLines.`qty` > 0
AND Invoices.invoiceID = MAX(Invoices.invoiceID)
Which returns "Invalid use of group function".
Thanks in advance!
Assuming all invoices have invoice lines, you can use a subquery just on Invoices:
SELECT *
FROM (SELECT i.*
FROM Invoices i
WHERE i.orderID = 3829
ORDER BY i.invoiceID DESC
LIMIT 1
) i JOIN
InvoiceLines il
ON i.invoiceID = il.invoiceID JOIN
DistributorOrdersTbl d
ON d.distOrderRecID = i.orderID
WHERE il.qty > 0;

How to do a Query on SQL Server 2008 R2 using a subquery / function on GROUP BY

When I execute this query, it works fine:
SELECT
pr.pr_nombre , cl.cl_nomcorto,
mc_cant * dbo.tipo_cambio(cr.mo_id,3,mc_fecha)/0.951 as Interes,
mc_cant * dbo.tipo_cambio(cr.mo_id,3,mc_fecha)/0.951*.049 as WH,
(select pr_id from dbo.nonplusultra(cr.pr_id) where pr_renew_ref is null) as Agrupador
FROM movcuentas mc
inner join corridas cr on mc.cr_id = cr.cr_id
inner join clientes cl on cr.cl_id = cl.cl_id
inner join prestamos pr on cr.pr_id = pr.pr_id
WHERE (mc_concepto = 'Amort Int') AND (tm_id = 3) AND MONTH(mc_fecha) = 2 AND YEAR(mc_fecha) = 2017
ORDER BY pr.pr_nombre
I get this:
Query results
Now I need to show it adding columns "Interes" and "WH" on records with same "Agrupador", something like this:
SELECT
pr.pr_nombre , cl.cl_nomcorto,
sum(mc_cant * dbo.tipo_cambio(cr.mo_id,3,mc_fecha)/0.951) as Interes,
sum(mc_cant * dbo.tipo_cambio(cr.mo_id,3,mc_fecha)/0.951*.049) as WH,
(select pr_id from dbo.nonplusultra(cr.pr_id) where pr_renew_ref is null) as Agrupador
FROM movcuentas mc
inner join corridas cr on mc.cr_id = cr.cr_id
inner join clientes cl on cr.cl_id = cl.cl_id
inner join prestamos pr on cr.pr_id = pr.pr_id
WHERE (mc_concepto = 'Amort Int') AND (tm_id = 3) AND MONTH(mc_fecha) = 2 AND YEAR(mc_fecha) = 2017
GROUP BY pr.pr_nombre , cl.cl_nomcorto, (select pr_id from dbo.nonplusultra(cr.pr_id) where pr_renew_ref is null)
ORDER BY pr.pr_nombre
And I get this error message:
Msg 144, Level 15, State 1, Line 12
Cannot use an aggregate or a subquery in an expression used for the group by list of a GROUP BY clause.
Any help will be welcome.
Can you make use of CTE here?
;WITH CTE as
(
SELECT
pr.pr_nombre , cl.cl_nomcorto,
mc_cant * dbo.tipo_cambio(cr.mo_id,3,mc_fecha)/0.951 as Interes,
mc_cant * dbo.tipo_cambio(cr.mo_id,3,mc_fecha)/0.951*.049 as WH,
(select pr_id from dbo.nonplusultra(cr.pr_id) where pr_renew_ref is null) as Agrupador
FROM movcuentas mc
inner join corridas cr on mc.cr_id = cr.cr_id
inner join clientes cl on cr.cl_id = cl.cl_id
inner join prestamos pr on cr.pr_id = pr.pr_id
WHERE (mc_concepto = 'Amort Int') AND (tm_id = 3) AND MONTH(mc_fecha) = 2 AND YEAR(mc_fecha) = 2017
ORDER BY pr.pr_nombre
)
select pr_nombre,cl_nomcorto,sum(Interes),sum(WH),Agrupador
from CTE
group by pr_nombre,cl_nomcorto,Agrupador
order by pr_nombre

Is there any alternate way to select the values in this case statement rather than subqueries

I know some degree of MySQL, but I'm not sure if there's a more correct way to do what I'm doing here.
#Select Ticket ID, Ticket Title, Assigned To
SELECT * FROM
(SELECT
ti.number, ti.ticket_id, foev.value AS "ticket_name",
CASE WHEN ti.staff_id = 0 AND ti.team_id = 0
then
"** Unassigned **"
ELSE
CASE when ti.staff_id = 0
THEN
(SELECT te.name FROM ost_team te WHERE te.team_id = ti.team_id)
ELSE
(SELECT CONCAT(st.firstname,LEFT(st.lastname,1)) FROM ost_staff st WHERE st.staff_id = ti.staff_id)
END
END AS "assigned_to"
FROM ost_ticket ti
LEFT JOIN ost_form_entry foe ON foe.object_id = ti.ticket_id AND foe.object_type = "T"
LEFT JOIN ost_form_entry_values foev ON foev.entry_id = foe.id
GROUP BY ti.ticket_id)
AS ticket_meta_list
ORDER BY ticket_id ASC;
Is there a more correct way to do those subqueries? I'm thinking there may be with joins that I'm less familiar with.
If your staff table has no staff_id with value 0, and your team table has no team_id with value 0, you can use left join in combination with coalesce:
SELECT ti.number,
ti.ticket_id,
foev.value AS ticket_name,
COALESCE(CONCAT(st.firstname,LEFT(st.lastname,1)),
te.name, '** Unassigned **') AS assigned_to
FROM ost_ticket ti
LEFT JOIN ost_form_entry foe
ON foe.object_id = ti.ticket_id
AND foe.object_type = 'T'
LEFT JOIN ost_form_entry_values foev
ON foev.entry_id = foe.id
LEFT JOIN ost_team te
ON te.team_id = ti.team_id
LEFT JOIN ost_staff st
ON st.staff_id = ti.staff_id
GROUP BY ti.ticket_id
ORDER BY ticket_id

use subquery in inner join mysql

This is my query
SELECT CONCAT(`SM_Title`,' ',`SM_Full_Name`) AS NAME,
`RG_Date`,
`RG_Reg_No`,
`RG_Stu_ID`,
`SM_Tell_Mobile`,
`SM_Tel_Residance`,
`RG_Reg_Type`,
Default_Batch,
`RG_Status`,
`RG_Final_Fee`,
`RG_Total_Paid`,
(`RG_Final_Fee`-`RG_Total_Paid`) AS TOTALDUE,
SUM(`SI_Ins_Amount` - `SI_Paid_Amount`) AS AS_AT_APRIAL_END
INNER JOIN
(SELECT `SI_Ins_Amount`,
`SI_Reg_No`
FROM
`student_installments`
GROUP BY MONTHNAME(`SI_Due_Date`)) Z ON
Z.`SI_Reg_No` = `registrations`.`RG_Reg_No`
FROM `registrations`
LEFT JOIN `student_master` ON `student_master`.`SM_ID` = `registrations`.`RG_Stu_ID`
LEFT JOIN `student_installments` ON `student_installments`.`SI_Reg_No` = `registrations`.`RG_Reg_No`
WHERE (`RG_Reg_Type` LIKE '%HND%' OR `RG_Reg_Type` LIKE '%LMU%' )
AND `SI_Due_Date` <= '2014-04-30' GROUP BY `SI_Reg_No`
It gave me an error near
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Z LIMIT 0, 25' at line 1
SELECT
CONCAT(SM_Title,' ',SM_Full_Name) AS NAME,
RG_Date,
RG_Reg_No,
RG_Stu_ID,
SM_Tell_Mobile,
SM_Tel_Residance,
RG_Reg_Type,
Default_Batch,
RG_Status,
RG_Final_Fee,
RG_Total_Paid,
(RG_Final_Fee-RG_Total_Paid) AS TOTALDUE,
SUM(SI_Ins_Amount - SI_Paid_Amount) AS AS_AT_APRIAL_END
FROM registrations
INNER JOIN
(SELECT SI_Ins_Amount,SI_Reg_No
FROM student_installments
GROUP BY MONTHNAME(SI_Due_Date)) Z ON Z.SI_Reg_No = registrations.RG_Reg_No
LEFT JOIN student_master ON student_master.SM_ID = registrations.RG_Stu_ID
LEFT JOIN student_installments ON student_installments.SI_Reg_No = registrations.RG_Reg_No
WHERE (RG_Reg_Type LIKE '%HND%' OR RG_Reg_Type LIKE '%LMU%' )
AND SI_Due_Date <= '2014-04-30'
GROUP BY SI_Reg_No
I notice you have fogotten the left table or subselect that you want to join to the (SELECT SI_INs .....) and previous this I could see there is no from clause before join.
I hope this helps you
Regards
You are using from clause in wrong position it should be just after selection of your columns, you can use below query:
SELECT
CONCAT(SM_Title,' ',SM_Full_Name) AS NAME ,RG_Date,RG_Reg_No,RG_Stu_ID,SM_Tell_Mobile,SM_Tel_Residance,RG_Reg_Type,Default_Batch,RG_Status,RG_Final_Fee,RG_Total_Paid,(RG_Final_Fee-RG_Total_Paid) AS TOTALDUE, SUM(SI_Ins_Amount - SI_Paid_Amount) AS AS_AT_APRIAL_END
FROM registrations AS reg
JOIN
(SELECT
SI_Ins_Amount,SI_Reg_No
FROM student_installments
GROUP BY MONTHNAME(SI_Due_Date)) AS Z
ON Z.SI_Reg_No = reg.RG_Reg_No
LEFT JOIN student_master AS sm
ON sm.SM_ID = reg.RG_Stu_ID
LEFT JOIN student_installments AS si
ON si.SI_Reg_No = reg.RG_Reg_No
WHERE (RG_Reg_Type LIKE '%HND%' OR RG_Reg_Type LIKE '%LMU%' ) AND SI_Due_Date <= '2014-04-30'
GROUP BY SI_Reg_No;
In the part below, from keyword should go before the inner join:
FROM registrations
INNER JOIN
(SELECT SI_Ins_Amount,
SI_Reg_No
FROM student_installments
GROUP BY MONTHNAME(SI_Due_Date)
) Z
ON Z.SI_Reg_No = registrations.RG_Reg_No

SELECT INTO Statement Failed

Can you guys guide me as to why this does not work?
SELECT AN.an_id, AN.an_name,
(SELECT TOP(1)ex_date
FROM upd_exam_headers
WHERE HS.an_id = AN.an_id
ORDER BY ex_date desc),
sum(ex_fee)
INTO upd_nc_felines AS FS
FROM upd_animals AS AN
LEFT JOIN upd_exam_headers AS HS ON HS.an_id = AN.an_id
LEFT JOIN upd_exam_details AS DS ON DS.ex_id = HS.ex_id
WHERE an_type = 'cat' and an_status = 'NC'
GROUP BY AN.an_id, AN.an_name;
Msg 156, Level 15, State 1, Line 10
Incorrect syntax near the keyword 'AS'.
The error message says what it means :)
Add an alias to sum(ex_fee)
Give a try to this, hope should work,
WITH TMP AS (
SELECT
AN.an_id, AN.an_name,
(SELECT TOP 1 ex_date
FROM upd_exam_headers
WHERE HS.an_id = AN.an_id
ORDER BY ex_date desc) AS 'ex_date',
sum(ex_fee) AS 'ex_fee'
FROM upd_animals AS AN
LEFT JOIN upd_exam_headers AS HS ON HS.an_id = AN.an_id
LEFT JOIN upd_exam_details AS DS ON DS.ex_id = HS.ex_id
WHERE an_type = 'cat' and an_status = 'NC'
GROUP BY AN.an_id, AN.an_name;
)
SELECT * INTO
upd_nc_felines
FROM TMP