Syntax error with Complex MySQL Procedure/Function - mysql

I have come up with a fairly complex query that computes and returns two date fields based on some input arguments. These date values need to be further used in a report which will have lots of other fields. As you can see there are 4 input variables and 2 output variables.
set #caSplit = 0.3;
set #flSplit = 0.7;
set #formulaForAvgUsed='useAvgOfAll';
set #itemNumber = 'TAB_120_IVR_POLY';
select
max(case when compCA >0 then rollingDate else current_date end) as oosDateForCA,
max(case when compFL >0 then rollingDate else current_date END) as oosDateForFL
from
(
select
items.item, items.rollingDate, perDaySalesCA, perDaySalesFL,
items.total_items_in_ca, total_items_in_fl, flAsnItems.flASNQty, caAsnItems.caASNQty,
#prevDayCA := case
when cntr = 0 then total_items_in_ca
when greatest(#prevDayCA,0) + coalesce(caASNQty,0) = 0 then 0
else greatest(#prevDayCA,0) - perDaySalesCA - IF(#prevDayFL > perDaySalesFL, 0, perDaySalesFL) + coalesce(caASNQty,0)
end as compCA,
#prevDayCA as caInv,
#prevDayFL := case
when cntr = 0 then total_items_in_fl
when greatest(#prevDayFL,0) + coalesce(flASNQty,0) = 0 then 0
else greatest(#prevDayFL,0) - perDaySalesFL - IF(#prevDayCA > perDaySalesCA, 0, perDaySalesCA) + coalesce(flAsnQty, 0)
end as compFL,
#prevDayFL as flInv
from
(select #prevDayCA := -1, #prevDayFL := -1)vars,
(
select
item, total_items_in_fl, total_items_in_ca,
ROUND(avgToUse * #caSplit / 30) as perDaySalesCA,
ROUND(avgToUse * #flSplit / 30) as perDaySalesFL,
#cntr as cntr,
DATE_ADD(current_date, INTERVAL #cntr DAY) as rollingDate,
#cntr := #cntr + 1
from
(
select
#cntr := 0
) vars
join counter c
join
(
select
i.number as item, i.total_items_in_ca, i.total_items_in_fl,
case when #formulaForAvgUsed = 'useNewMSA' then
i.new_msa
when #formulaForAvgUsed = 'useMSA' then
i.monthly_sales_average
when #formulaForAvgUsed = 'useWMSA' then
i.weighted_monthly_sales_average
when #formulaForAvgUsed = 'useTwoWeeks' then
i.two_wks_average * 2
when #formulaForAvgUsed = 'useMaxAvg' then
greatest(i.new_msa, i.monthly_sales_average, i.weighted_monthly_sales_average, i.two_wks_average *2)
when #formulaForAvgUsed = 'useAvgOfAll' then
case when DATE_ADD(i.first_sold_date, INTERVAL 365 DAY) > CURRENT_DATE then
(i.new_msa + i.two_wks_average *2 + i.monthly_sales_average)/3
else
(i.new_msa + i.two_wks_average *2 + i.monthly_sales_average+ i.weighted_monthly_sales_average)/4
end
when #formulaForAvgUsed = 'useAvgMSAAndNewMSA' then
(i.new_msa + i.monthly_sales_average)/2
when #formulaForAvgUsed = 'useAvgWMSAAndTwoWeeks' then
case when DATE_ADD(i.first_sold_date, INTERVAL 365 DAY) < CURRENT_DATE then
i.weighted_monthly_sales_average
else
( i.two_wks_average *2 + i.weighted_monthly_sales_average)/2
end
else
greatest(i.new_msa, i.monthly_sales_average, i.weighted_monthly_sales_average, i.two_wks_average *2)
end as avgToUse
from
item i
where
i.number = #itemNumber
) T
) items
left join
(
select
i.number, date(estimated_arrival_date) as asnDate,
sum((aol.loaded_quantity - aol.received_Quantity) * p.quantity) as caASNQty
from
item i join asn_order_line aol on aol.item_id = i.item_id
join asn_order ao on ao.asn_order_id = aol.asn_order_id
join pack p on aol.pack_id = p.pack_id
where
aol.line_status = 'New' and ao.status in ('New' , 'Partial Receipt', 'Receiving', 'Partially Received')
and facility = 'WHSE'
and i.number = #itemNumber
group by
i.number, date(estimated_arrival_date)
) caAsnItems on caAsnItems.number = items.item and caAsnItems.asnDate = rollingDate
left join
(
select
i.number,
date(estimated_arrival_date) as asnDate,
sum((aol.loaded_quantity - aol.received_Quantity) * p.quantity) as flASNQty
from
item i join asn_order_line aol on aol.item_id = i.item_id
join asn_order ao on ao.asn_order_id = aol.asn_order_id
join pack p on aol.pack_id = p.pack_id
where
aol.line_status = 'New' and ao.status in ('New' , 'Partial Receipt', 'Receiving', 'Partially Received')
and facility = 'FLOR'
and i.number = #itemNumber
group by
i.number, date(estimated_arrival_date)
) flAsnItems on flAsnItems.number = items.item and flAsnItems.asnDate = rollingDate
group by
rollingDate
having
caInv > 0 || flInv > 0
|| rollingDate <= greatest(max(flAsnItems.asnDate), max(caAsnItems.asnDate))
order by
rollingDate DESC
)top;
My intent is to create a procedure and select the values in the top level into the output variables. Using MySQL Workbench when I try to create with this syntax, it throws a syntax error but doesn't say what exactly is the issue.
DELIMITER //
CREATE PROCEDURE `compute_oos_date2` (IN itemNumber VARCHAR(50), IN formulaForAvgUsed VARCHAR(50), IN caSplit FLOAT, IN flSplit FLOAT, OUT oosDateForCA DATE, OUT oosDateForFL DATE)
BEGIN
SET #prevDayCA = -1;
SET #prevDayFL = -1;
select
max(case when compCA >0 then rollingDate else current_date end) into oosDateForCA,
max(case when compFL >0 then rollingDate else current_date END) into oosDateForFL
from
(
select
items.item, items.rollingDate, perDaySalesCA, perDaySalesFL,
items.total_items_in_ca, total_items_in_fl, flAsnItems.flASNQty, caAsnItems.caASNQty,
#prevDayCA := case
when cntr = 0 then total_items_in_ca
when greatest(#prevDayCA,0) + coalesce(caASNQty,0) = 0 then 0
else greatest(#prevDayCA,0) - perDaySalesCA - IF(#prevDayFL > perDaySalesFL, 0, perDaySalesFL) + coalesce(caASNQty,0)
end as compCA,
#prevDayCA as caInv,
#prevDayFL := case
when cntr = 0 then total_items_in_fl
when greatest(#prevDayFL,0) + coalesce(flASNQty,0) = 0 then 0
else greatest(#prevDayFL,0) - perDaySalesFL - IF(#prevDayCA > perDaySalesCA, 0, perDaySalesCA) + coalesce(flAsnQty, 0)
end as compFL,
#prevDayFL as flInv
from
(
select
item, total_items_in_fl, total_items_in_ca,
ROUND(avgToUse * caSplit / 30) as perDaySalesCA,
ROUND(avgToUse * flSplit / 30) as perDaySalesFL,
#cntr as cntr,
DATE_ADD(current_date, INTERVAL #cntr DAY) as rollingDate,
#cntr := #cntr + 1
from
(select #cntr := 0) vars
join counter c
join
(
select
i.number as item, i.total_items_in_ca, i.total_items_in_fl,
case when formulaForAvgUsed = 'useNewMSA' then
i.new_msa
when formulaForAvgUsed = 'useMSA' then
i.monthly_sales_average
when formulaForAvgUsed = 'useWMSA' then
i.weighted_monthly_sales_average
when formulaForAvgUsed = 'useTwoWeeks' then
i.two_wks_average * 2
when formulaForAvgUsed = 'useMaxAvg' then
greatest(i.new_msa, i.monthly_sales_average, i.weighted_monthly_sales_average, i.two_wks_average *2)
when formulaForAvgUsed = 'useAvgOfAll' then
case when DATE_ADD(i.first_sold_date, INTERVAL 365 DAY) > CURRENT_DATE then
(i.new_msa + i.two_wks_average *2 + i.monthly_sales_average)/3
else
(i.new_msa + i.two_wks_average *2 + i.monthly_sales_average+ i.weighted_monthly_sales_average)/4
end
when formulaForAvgUsed = 'useAvgMSAAndNewMSA' then
(i.new_msa + i.monthly_sales_average)/2
when formulaForAvgUsed = 'useAvgWMSAAndTwoWeeks' then
case when DATE_ADD(i.first_sold_date, INTERVAL 365 DAY) < CURRENT_DATE then
i.weighted_monthly_sales_average
else
( i.two_wks_average *2 + i.weighted_monthly_sales_average)/2
end
else
greatest(i.new_msa, i.monthly_sales_average, i.weighted_monthly_sales_average, i.two_wks_average *2)
end as avgToUse
from
item i
where
i.number = itemNumber
) T
) items
left join
(
select
i.number, date(estimated_arrival_date) as asnDate,
sum((aol.loaded_quantity - aol.received_Quantity) * p.quantity) as caASNQty
from
item i join asn_order_line aol on aol.item_id = i.item_id
join asn_order ao on ao.asn_order_id = aol.asn_order_id
join pack p on aol.pack_id = p.pack_id
where
aol.line_status = 'New' and ao.status in ('New' , 'Partial Receipt', 'Receiving', 'Partially Received')
and facility = 'WHSE'
and i.number= itemNumber
group by
i.number, date(estimated_arrival_date)
) caAsnItems on caAsnItems.number = items.item and caAsnItems.asnDate = rollingDate
left join
(
select
i.number,
date(estimated_arrival_date) as asnDate,
sum((aol.loaded_quantity - aol.received_Quantity) * p.quantity) as flASNQty
from
item i join asn_order_line aol on aol.item_id = i.item_id
join asn_order ao on ao.asn_order_id = aol.asn_order_id
join pack p on aol.pack_id = p.pack_id
where
aol.line_status = 'New' and ao.status in ('New' , 'Partial Receipt', 'Receiving', 'Partially Received')
and facility = 'FLOR'
and i.number = itemNumber
group by
i.number, date(estimated_arrival_date)
) flAsnItems on flAsnItems.number = items.item and flAsnItems.asnDate = rollingDate
group by
rollingDate
having
caInv > 0 || flInv > 0
|| rollingDate <= greatest(max(flAsnItems.asnDate), max(caAsnItems.asnDate))
order by
rollingDate DESC
)top
END //
DELIMITER;
Can anyone help ?

I figured out , the syntax to load into multiple variables is
select 'abc', 'def' into var1, var2
Earlier I was using
select 'abc' into var1, 'def' into var2

Related

Snowflake Function input is datetime, but when i call the function it's not quite working

with temp AS (
SELECT CAST(SUM(sreg.ScrapQuantity) AS INT) AS Quantity,
sreas.Name AS ScrapReason,
to_date((DATEADD(MINUTE, 30 * (DATE_PART(MINUTE, sreg.ScrapTime) / 30), DATEADD(HOUR, TIMESTAMPDIFF(HOUR, '0', sreg.ScrapTime), '0')))) AS DATETIME,
sreg.EquipmentID AS EquipmentID
FROM ScrapRegistration sreg
INNER JOIN ScrapReason sreas ON sreas.ID = sreg.ScrapReasonID
INNER JOIN WorkRequest wr ON wr.ID = sreg.WorkRequestID
INNER JOIN SegmentRequirementEquipmentRequirement srer ON srer.SegmentRequirementID = wr.SegmentRequirementID
GROUP BY DATEADD(MINUTE, 30 * (DATE_PART(MINUTE, sreg.ScrapTime) / 30), DATEADD(HOUR, TIMESTAMPDIFF(HOUR, '0', sreg.ScrapTime), '0')),
sreg.EquipmentID,
sreas.Name
)
select temp.EquipmentID
from RAW_CPMS_AAR.equipment e, temp
Where e.ID = (select * from table(cfn_GetShiftIDFromDateTime_test(temp.DateTime::DATETIME, 0))) --this works with datetime
when i run this query above, i get Processing aborted due to error 300010:391167117; incident 3245754.. I believe this is an issue with the temp.datetime -- when i run the same codebut hardcoding the function input, i get the desired output.
with temp AS (
SELECT CAST(SUM(sreg.ScrapQuantity) AS INT) AS Quantity,
sreas.Name AS ScrapReason,
to_date((DATEADD(MINUTE, 30 * (DATE_PART(MINUTE, sreg.ScrapTime) / 30), DATEADD(HOUR, TIMESTAMPDIFF(HOUR, '0', sreg.ScrapTime), '0')))) AS DATETIME,
sreg.EquipmentID AS EquipmentID
FROM ScrapRegistration sreg
INNER JOIN ScrapReason sreas ON sreas.ID = sreg.ScrapReasonID
INNER JOIN WorkRequest wr ON wr.ID = sreg.WorkRequestID
INNER JOIN SegmentRequirementEquipmentRequirement srer ON srer.SegmentRequirementID = wr.SegmentRequirementID
GROUP BY DATEADD(MINUTE, 30 * (DATE_PART(MINUTE, sreg.ScrapTime) / 30), DATEADD(HOUR, TIMESTAMPDIFF(HOUR, '0', sreg.ScrapTime), '0')),
sreg.EquipmentID,
sreas.Name
)
select temp.EquipmentID
from RAW_CPMS_AAR.equipment e, temp
Where e.ID = (select * from table(cfn_GetShiftIDFromDateTime_test('2021-12-02 10:03:0.00'::datetime, 0))) --this works with datetime
it seems that that somwehere along the line, it's not liking the date format i put in. it's not returning me an error of not liking the input.
here is the function.
CREATE OR REPLACE FUNCTION DB_BI_DEV.RAW_CPMS_AAR.cfn_GetShiftIDFromDateTime (dateTime TIMESTAMP_NTZ(9), shiftCalendarID int)
RETURNS table (shiftID int)
AS
$$
WITH T0 (ShiftCalendarID, CurDay, PrvDay)
AS (
SELECT TOP 1
ID AS ShiftCalendarID,
DATEDIFF( day, BeginDate, dateTime ) % PeriodInDays + 1 AS CurDay,
( CurDay + PeriodInDays - 2 ) % PeriodInDays + 1 AS PrvDay
FROM RAW_CPMS_AAR.ShiftCalendar
WHERE ID = shiftCalendarID
OR ( shiftCalendarID IS NULL
AND Name = 'Factory'
AND BeginDate <= dateTime )
ORDER BY BeginDate DESC
),
T1 (TimeValue)
AS (
SELECT TIME_FROM_PARTS(
EXTRACT(HOUR FROM dateTime),
EXTRACT(MINUTE FROM dateTime),
EXTRACT(SECOND FROM dateTime))
)
SELECT ID as shiftID
FROM RAW_CPMS_AAR.Shift, T0, T1
WHERE Shift.ShiftCalendarID = T0.ShiftCalendarID
AND ( ( FromDay = T0.CurDay AND FromTimeOfDay <= T1.TimeValue AND TillTimeOfDay > T1.TimeValue )
OR ( FromDay = T0.CurDay AND FromTimeOfDay >= TillTimeOfDay AND FromTimeOfDay <= T1.TimeValue )
OR ( FromDay = T0.PrvDay AND FromTimeOfDay >= TillTimeOfDay AND TillTimeOfDay > T1.TimeValue )
)
$$
;

SQLSERVER Running Balance

Actually i have problem on my query to get the running balance , i have debit and credit transaction i need one column to showing the cumulative running balance this is the code i used :
Select * From (
Select D.AccNo, H.[Date], A.AccountName, H.TrxNo,
(Case When ((D.Remark = '') or (D.Remark is Null)) Then H.Trxnote Else D.Remark End) As TrxDetailDescA,
(D.Debit * 1) AS DebitValue, (D.Credit * 1) AS CreditValue,SUM(COALESCE(D.Debit, 0) - COALESCE(D.Credit, 0)) AS Balance
From TblHeadTrans H, TblTransDetails D, TblAccount A
Where H.Guid = D.[LineNo]
And D.AccNo = A.AccountNo
And H.[Date] >= '01-01-2022' And H.[Date] <= '10-07-2022' And D.AccNo >= '1003'
group by AccNo,H.[Date],A.AccountName,H.TrxNo,D.Remark,h.Trxnote,d.Debit,d.Credit
Union All
Select D.AccNo, Null As TrxDate, A.AccountName, Null As TrxNo,
'Opening Balance' As TrxDetailDesc,
Case When (Sum(D.Debit * 1) - Sum(D.Credit *1)) < 0 then 0
Else (Sum(D.Debit * 1) - Sum(D.Credit * 1)) End As DebitValue,
Case When (Sum(D.Credit * 1) - Sum(D.Debit * 1)) < 0 then 0
Else (Sum(D.Credit * 1) - Sum(D.Debit * 1)) End As CreditValue
, SUM(COALESCE(d.Debit, 0) - COALESCE(d.credit, 0)) AS Balance
From TblHeadTrans H, TblTransDetails D, TblAccount A
Where H.guid = D.[LineNo] And D.AccNo = A.AccountNo
And d.[Date] < '01-01-2022' And D.accno = '1003'
Group By D.AccNo, A.AccountName,H.Date,H.TrxNo
) ReportData
WHERE 1=1
Order By AccNo, [Date], TrxNo
and the result showing as the picture:
the result

How to Group This SQL

The SQL statement below produce sums of data for months and displays the columns as years.
The problem, as you will see in the image below, is that the result set has null values. Is there a way to represent the dataset for each month once?
SELECT
DATE_FORMAT(start_date, '%M') AS M,
(CASE DATE_FORMAT(start_date, '%Y')
WHEN
2015
THEN
ROUND((COALESCE(SUM(b.bid_amount), 0) + COALESCE(SUM(b.hourly_bid_amount), 0) + COALESCE(SUM(b.other_bid_amount), 0) * pcntg.percentage / 100 + SUM(b.other_bid_amount) - COALESCE(SUM(b.subcontracted_amount), 0)),
2) + COALESCE(SUM(b.subcontracted_amount), 0) + COALESCE(SUM(b.contingency_1), 0)
END) AS '2015',
(CASE DATE_FORMAT(start_date, '%Y')
WHEN
2016
THEN
ROUND((COALESCE(SUM(b.bid_amount), 0) + COALESCE(SUM(b.hourly_bid_amount), 0) + COALESCE(SUM(b.other_bid_amount), 0) * pcntg.percentage / 100 + SUM(b.other_bid_amount) - COALESCE(SUM(b.subcontracted_amount), 0)),
2) + COALESCE(SUM(b.subcontracted_amount), 0) + COALESCE(SUM(b.contingency_1), 0)
END) AS '2016',
(CASE DATE_FORMAT(start_date, '%Y')
WHEN
2017
THEN
ROUND((COALESCE(SUM(b.bid_amount), 0) + COALESCE(SUM(b.hourly_bid_amount), 0) + COALESCE(SUM(b.other_bid_amount), 0) * pcntg.percentage / 100 + SUM(b.other_bid_amount) - COALESCE(SUM(b.subcontracted_amount), 0)),
2) + COALESCE(SUM(b.subcontracted_amount), 0) + COALESCE(SUM(b.contingency_1), 0)
END) AS '2017',
(CASE DATE_FORMAT(start_date, '%Y')
WHEN
2018
THEN
ROUND((COALESCE(SUM(b.bid_amount), 0) + COALESCE(SUM(b.hourly_bid_amount), 0) + COALESCE(SUM(b.other_bid_amount), 0) * pcntg.percentage / 100 + SUM(b.other_bid_amount) - COALESCE(SUM(b.subcontracted_amount), 0)),
2) + COALESCE(SUM(b.subcontracted_amount), 0) + COALESCE(SUM(b.contingency_1), 0)
END) AS '2018'
FROM
phases_required b
RIGHT JOIN
projects a ON b.project_id = a.id
LEFT JOIN
(SELECT
t2.project_id, ROUND(reimbursable_percent, 0) AS percentage
FROM
rate_names t1, phases_required t2, rates_phase t3
WHERE
t1.id = t3.rate_names_id
AND t3.rates_id = t2.rates_id
GROUP BY t2.project_id) AS pcntg ON pcntg.project_id = a.id
WHERE
start_date != '0000-00-00'
AND DATE_FORMAT(start_date, '%Y') NOT IN (2010 , 2012, 2013, 2014)
GROUP by DATE_FORMAT(start_date, '%m%Y')
Here is the SQL to produce the table SQL statement you see above dynamically:
SET SESSION group_concat_max_len = 10000000000;
SET #sqldynamic = (
SELECT
GROUP_CONCAT( distinct
CONCAT( '(case date_format(start_date,"%Y") when ', date_format(a.start_date,"%Y") , ' then ROUND((COALESCE(sum(b.bid_amount), 0) + COALESCE(sum(b.hourly_bid_amount),0) + COALESCE(sum(b.other_bid_amount), 0) * pcntg.percentage/100 + sum(b.other_bid_amount) - COALESCE(sum(b.subcontracted_amount),0)),2)+COALESCE(sum(b.subcontracted_amount),0)+COALESCE(sum(b.contingency_1),0) end) as \'' , date_format(start_date,"%Y"),'\''
)
)
From phases_required b RIGHT JOIN projects a ON b.project_id = a.id LEFT JOIN (SELECT t2.project_id, round(reimbursable_percent,0) as percentage FROM rate_names t1,phases_required t2,rates_phase t3
WHERE t1.id = t3.rate_names_id AND t3.rates_id = t2.rates_id group by t2.project_id) as pcntg on pcntg.project_id =a.id
WHERE start_date != "0000-00-00" and date_format(start_date,"%Y") not in (2010,2012,2013,2014)
);
SET #sql = CONCAT('SELECT date_format(start_date,"%M") as M, ',
#sqldynamic, '
From phases_required b RIGHT JOIN projects a ON b.project_id = a.id LEFT JOIN (SELECT t2.project_id, round(reimbursable_percent,0) as percentage FROM rate_names t1,phases_required t2,rates_phase t3
WHERE t1.id = t3.rate_names_id AND t3.rates_id = t2.rates_id group by t2.project_id) as pcntg on pcntg.project_id =a.id
WHERE start_date != "0000-00-00" and date_format(start_date,"%Y") not in (2010,2012,2013,2014)
group by date_format(start_date,"%M%Y") order by date_format(start_date,"%m")'
);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I don't like but it should works :
select m,
sum(coalesce('2015', 0)) '2015',
sum(coalesce('2015', 0)) '2016',
sum(coalesce('2015', 0)) '2017',
sum(coalesce('2015', 0)) '2018'
from (
SELECT
DATE_FORMAT(start_date, '%M') AS M,
(CASE DATE_FORMAT(start_date, '%Y')
WHEN
2015
THEN
ROUND((COALESCE(SUM(b.bid_amount), 0) + COALESCE(SUM(b.hourly_bid_amount), 0) + COALESCE(SUM(b.other_bid_amount), 0) * pcntg.percentage / 100 + SUM(b.other_bid_amount) - COALESCE(SUM(b.subcontracted_amount), 0)),
2) + COALESCE(SUM(b.subcontracted_amount), 0) + COALESCE(SUM(b.contingency_1), 0)
END) AS '2015',
(CASE DATE_FORMAT(start_date, '%Y')
WHEN
2016
THEN
ROUND((COALESCE(SUM(b.bid_amount), 0) + COALESCE(SUM(b.hourly_bid_amount), 0) + COALESCE(SUM(b.other_bid_amount), 0) * pcntg.percentage / 100 + SUM(b.other_bid_amount) - COALESCE(SUM(b.subcontracted_amount), 0)),
2) + COALESCE(SUM(b.subcontracted_amount), 0) + COALESCE(SUM(b.contingency_1), 0)
END) AS '2016',
(CASE DATE_FORMAT(start_date, '%Y')
WHEN
2017
THEN
ROUND((COALESCE(SUM(b.bid_amount), 0) + COALESCE(SUM(b.hourly_bid_amount), 0) + COALESCE(SUM(b.other_bid_amount), 0) * pcntg.percentage / 100 + SUM(b.other_bid_amount) - COALESCE(SUM(b.subcontracted_amount), 0)),
2) + COALESCE(SUM(b.subcontracted_amount), 0) + COALESCE(SUM(b.contingency_1), 0)
END) AS '2017',
(CASE DATE_FORMAT(start_date, '%Y')
WHEN
2018
THEN
ROUND((COALESCE(SUM(b.bid_amount), 0) + COALESCE(SUM(b.hourly_bid_amount), 0) + COALESCE(SUM(b.other_bid_amount), 0) * pcntg.percentage / 100 + SUM(b.other_bid_amount) - COALESCE(SUM(b.subcontracted_amount), 0)),
2) + COALESCE(SUM(b.subcontracted_amount), 0) + COALESCE(SUM(b.contingency_1), 0)
END) AS '2018'
FROM
phases_required b
RIGHT JOIN
projects a ON b.project_id = a.id
LEFT JOIN
(SELECT
t2.project_id, ROUND(reimbursable_percent, 0) AS percentage
FROM
rate_names t1, phases_required t2, rates_phase t3
WHERE
t1.id = t3.rate_names_id
AND t3.rates_id = t2.rates_id
GROUP BY t2.project_id) AS pcntg ON pcntg.project_id = a.id
WHERE
start_date != '0000-00-00'
AND DATE_FORMAT(start_date, '%Y') NOT IN (2010 , 2012, 2013, 2014)
GROUP by DATE_FORMAT(start_date, '%m%Y')
) qry
group by m;
Here is the answer. Thank you Daniel Blais for helping getting me here.
SET SESSION group_concat_max_len = 10000000000;
SET #sqldynamic = (
SELECT
GROUP_CONCAT( distinct
CONCAT( '(case date_format(start_date,"%Y") when ', date_format(a.start_date,"%Y") , ' then ROUND((COALESCE(sum(b.bid_amount), 0) + COALESCE(sum(b.hourly_bid_amount),0) + COALESCE(sum(b.other_bid_amount), 0) * pcntg.percentage/100 + sum(b.other_bid_amount) - COALESCE(sum(b.subcontracted_amount),0)),2)+COALESCE(sum(b.subcontracted_amount),0)+COALESCE(sum(b.contingency_1),0) end) as Y_' , date_format(start_date,"%Y")
)
)
From phases_required b RIGHT JOIN projects a ON b.project_id = a.id LEFT JOIN (SELECT t2.project_id, round(reimbursable_percent,0) as percentage FROM rate_names t1,phases_required t2,rates_phase t3
WHERE t1.id = t3.rate_names_id AND t3.rates_id = t2.rates_id group by t2.project_id) as pcntg on pcntg.project_id =a.id
WHERE start_date != "0000-00-00" and date_format(start_date,"%Y") not in (2010,2012,2013,2014)
);
SET #sqlgroup = (
SELECT
GROUP_CONCAT(distinct
CONCAT('sum(coalesce(Y_', date_format(a.start_date,"%Y") ,', 0)) as Y_',date_format(a.start_date,"%Y")
)
)
From phases_required b RIGHT JOIN projects a ON b.project_id = a.id LEFT JOIN (SELECT t2.project_id, round(reimbursable_percent,0) as percentage FROM rate_names t1,phases_required t2,rates_phase t3
WHERE t1.id = t3.rate_names_id AND t3.rates_id = t2.rates_id group by t2.project_id) as pcntg on pcntg.project_id =a.id
WHERE start_date != "0000-00-00" and date_format(start_date,"%Y") not in (2010,2012,2013,2014)
);
SET #sql = CONCAT('select m,', #sqlgroup , ' from (SELECT date_format(start_date,"%M") as M, date_format(start_date,"%m") as m2 ,',
#sqldynamic, '
From phases_required b RIGHT JOIN projects a ON b.project_id = a.id LEFT JOIN (SELECT t2.project_id, round(reimbursable_percent,0) as percentage FROM rate_names t1,phases_required t2,rates_phase t3
WHERE t1.id = t3.rate_names_id AND t3.rates_id = t2.rates_id group by t2.project_id) as pcntg on pcntg.project_id =a.id
WHERE start_date != "0000-00-00" and date_format(start_date,"%Y") not in (2010,2012,2013,2014)
group by date_format(start_date,"%M%Y") order by date_format(start_date,"%m")) qry group by m order by m2'
);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

sql query with DISTINCT make huge performance issue

i have a query to get summary of donations
SELECT CONVERT(CHAR(2), CAST(pb.PayrollDate AS DATETIME), 101)
+ '/' + CONVERT(CHAR(4), CAST(pb.PayrollDate AS DATETIME), 120) AS Closing_Month ,
CONVERT(CHAR(6), CAST(pb.PayrollDate AS DATETIME), 112) AS Closing_Year ,
COUNT(DISTINCT Donation.Employee) + ( SELECT COUNT(*)
FROM dbo.Donation
INNER JOIN PayrollBatch pbd ON Donation.PayrollBatch = pbd.ID
WHERE CONVERT(CHAR(6), CAST(pbd.PayrollDate AS DATETIME), 112) = CONVERT(CHAR(6), CAST(pb.PayrollDate AS DATETIME), 112)
AND DonationType = 5
)AS 'Donors' ,
COUNT (DISTINCT( CASE WHEN Donation.DonationType = 1 OR Donation.DonationType = 5 THEN CharityDetails.ID
END ))AS 'Charities',
( CAST(COUNT(DISTINCT Donation.Employee) AS DECIMAL(18, 2))
/ ( SELECT SUM(NumberOfEmployees)
FROM OrganisationDetail
WHERE ID = Donation.OrganisationDetail
AND IsDeleted = 0
) ) * 100 AS 'Participation_Rate' ,
SUM(CASE WHEN Donation.DonationType = 1 OR Donation.DonationType = 5 THEN Donation.Amount
ELSE 0
END) AS 'Employee_Donations' ,
SUM(CASE WHEN Donation.DonationType = 2 THEN Donation.Amount
ELSE 0
END) AS 'Matched_Donations' ,
SUM(CASE WHEN Donation.DonationType = 1
OR Donation.DonationType = 2 OR Donation.DonationType = 5 THEN Donation.Amount
ELSE 0
END) AS 'Total_Donations'
FROM Donation
INNER JOIN OrganisationDetail AS OrganisationDetail_1 ON Donation.OrganisationDetail = OrganisationDetail_1.ID
INNER JOIN CharityProjectDetails ON Donation.CharityProjectDetails = CharityProjectDetails.ID
INNER JOIN CharityDetails ON CharityProjectDetails.CharityDetails = CharityDetails.ID
INNER JOIN PayrollBatch pb ON Donation.PayrollBatch = pb.ID
LEFT JOIN Employee ON Donation.Employee = Employee.ID
LEFT JOIN DonationIntent ON Donation.DonationIntent = DonationIntent.ID
LEFT JOIN EmployeeAddress ON Employee.ID = EmployeeAddress.Employee
LEFT JOIN dbo.PayrollBatchOther pbo ON pbo.PayrollBatch = pb.ID
GROUP BY CONVERT(CHAR(2), CAST(pb.PayrollDate AS DATETIME), 101)
+ '/' + CONVERT(CHAR(4), CAST(pb.PayrollDate AS DATETIME), 120) ,
CONVERT(CHAR(6), CAST(pb.PayrollDate AS DATETIME), 112) ,
Donation.OrganisationDetail
ORDER BY Closing_Year;
i need to get unique donors count from result set COUNT(DISTINCT e.ID) but with distinct query takes 7-9 sec to complete execution but without that it took only 1 sec how to improve that performance
Update
Here is the Paste The Plan

how to use clause(where,and,not) sql

I have table absen like this:
and the table itungharian with coloumn like this:
id_itung | id | total | itungtgl
(no data)
and query join like this:
SELECT
count(tgl) AS total,
absen.id,
pegawai.nama,
pegawai.bagian,
pegawai.bagian,
pegawai.tglmasuk,
gaji.jenis_gaji,
gaji.jumlah,
itungharian.id AS id2,
itungharian.itungtgl,
CASE
WHEN (weekday(tgl) <=3 )
THEN date(tgl + INTERVAL(3 - weekday(tgl)) DAY)
ELSE date(tgl + INTERVAL(3 + 7 - weekday(tgl)) DAY)
END AS tglitung
FROM
absen
JOIN
pegawai ON pegawai.id = absen.id
JOIN
gaji ON gaji.id = pegawai.id
LEFT JOIN
itungharian ON itungharian.id = absen.id
WHERE
absen.status = 'm'
GROUP BY
absen.id,
tglitung
and show this
So I have problem how to join like this if values on cloumn id(table absen) same with itungharian.tgl and tglitung(result case when) same with itungharian.itungtgl don't show in join table
I have tried with sql like this:
SELECT
count(tgl) AS total,
absen.id,
pegawai.nama,
pegawai.bagian,
pegawai.bagian,
pegawai.tglmasuk,
gaji.jenis_gaji,
gaji.jumlah,
itungharian.id AS id2,
itungharian.itungtgl,
CASE
WHEN (weekday(tgl) <= 3)
THEN date(tgl + INTERVAL(3 - weekday(tgl)) DAY)
ELSE date(tgl + INTERVAL(3 + 7 - weekday(tgl)) DAY)
END AS tglitung
FROM
absen
JOIN
pegawai ON pegawai.id = absen.id
JOIN
gaji ON gaji.id = pegawai.id
LEFT JOIN
itungharian ON itungharian.id = absen.id
WHERE
absen.status = 'm'
AND
NOT (CASE WHEN (weekday(tgl) <= 3)
THEN DATE(tgl + INTERVAL(3 - weekday(tgl)) DAY)
ELSE DATE(tgl + INTERVAL(3 + 7 - weekday(tgl)) DAY)END) = itungharian.itungtgl
AND
NOT absen.id = itungharian.id
GROUP BY
absen.id,
tglitung
but MySQL returned an empty result set (i.e. zero rows).