I am new to MYSQL.
I need to customize this query. Now I am using only the IF condition and the query length is too big.
In this stored procedure only we change 'f.status' value based on _status value
EX:
__status = 'ALL'
ON f.financeId = t.financeId where f.status=0;
__status = 'PAID'
ON f.financeId = t.financeId where f.status=1;
__status = 'UNPAID'
ON f.financeId = t.financeId where f.status=2;
Query:
DELIMITER ;;
CREATE DEFINER=`root`#`localhost` PROCEDURE `all_data_search`(
_status VARCHAR(50)
)
BEGIN
IF (_status='All') THEN
SELECT
f.financeId,
f.customerId,
c.customerName,
c.initial,
c.phone1,
c.aadhaar,
f.financeStartDate,
f.vehicleNumber,
f.loanAmount,
f.totalInstallment,
f.installmentAmount,
COALESCE(t.payedInstallment, 0) as payedInstallment,
f.status,
f.created_by,
f.created_date,
f.updated_by,
f.updated_date
FROM finance f
INNER JOIN customer c
ON c.customerId = f.customerId
LEFT JOIN
(
SELECT financeId, COUNT(status) AS payedInstallment
FROM financeinstallment
WHERE status = 1
GROUP BY financeId
) t
ON f.financeId = t.financeId;
END IF;
IF (_status='0') THEN
SELECT
f.financeId,
f.customerId,
c.customerName,
c.initial,
c.phone1,
c.aadhaar,
f.financeStartDate,
f.vehicleNumber,
f.loanAmount,
f.totalInstallment,
f.installmentAmount,
COALESCE(t.payedInstallment, 0) as payedInstallment,
f.status,
f.created_by,
f.created_date,
f.updated_by,
f.updated_date
FROM finance f
INNER JOIN customer c
ON c.customerId = f.customerId
LEFT JOIN
(
SELECT financeId, COUNT(status) AS payedInstallment
FROM financeinstallment
WHERE status = 1
GROUP BY financeId
) t
ON f.financeId = t.financeId where f.status=0;
END IF;
IF (_status = 'PAID') THEN
SELECT
f.financeId,
f.customerId,
c.customerName,
c.initial,
c.phone1,
c.aadhaar,
f.financeStartDate,
f.vehicleNumber,
f.loanAmount,
f.totalInstallment,
f.installmentAmount,
COALESCE(t.payedInstallment, 0) as payedInstallment,
f.status,
f.created_by,
f.created_date,
f.updated_by,
f.updated_date
FROM finance f
INNER JOIN customer c
ON c.customerId = f.customerId
LEFT JOIN
(
SELECT financeId, COUNT(status) AS payedInstallment
FROM financeinstallment
WHERE status = 1
GROUP BY financeId
) t
ON f.financeId = t.financeId where f.status=1;
END IF;
IF (_status = 'UNPAID') THEN
SELECT
f.financeId,
f.customerId,
c.customerName,
c.initial,
c.phone1,
c.aadhaar,
f.financeStartDate,
f.vehicleNumber,
f.loanAmount,
f.totalInstallment,
f.installmentAmount,
COALESCE(t.payedInstallment, 0) as payedInstallment,
f.status,
f.created_by,
f.created_date,
f.updated_by,
f.updated_date
FROM finance f
INNER JOIN customer c
ON c.customerId = f.customerId
LEFT JOIN
(
SELECT financeId, COUNT(status) AS payedInstallment
FROM financeinstallment
WHERE status = 1
GROUP BY financeId
) t
ON f.financeId = t.financeId where f.status=2;
END IF;
END ;;
DELIMITER ;
declare status_flag smallint;
....
IF (_status = 'ALL') THEN status_flag=0;
ELSEIF (_status = 'PAID') THEN status_flag=1;
ELSEIF (_status = 'UNPAID') THEN status_flag=2;
ENDIF;
....
WHERE status = status_flag
You can use boolean operation as follows:
ON f.financeId = t.financeId
where (__status = 'ALL' and f.status=0)
or (__status = 'PAID' and f.status=1)
or (__status = 'UNPAID' and f.status=2);
Related
I want to add a condition in the procedure, but I can't use (IF(Wh=0,'AND 1=1','AND D.wh_parn = 102'))
This is my procedure:
CREATE DEFINER=`akarremote`#`%` PROCEDURE `laporan_top_brand_penjualan`(IN Wh INT, IN `Datemin` VARCHAR(191), IN `Datemax` VARCHAR(191))
BEGIN
SELECT
A.item_id,
A.item_name AS ITEM,
(
SELECT
SUM( C.jumlah ) AS jumlah
FROM
mob_penjualan B
LEFT JOIN mob_penjualandetail C ON C.noTransaksi = B.noTransaksi
LEFT JOIN krd_wh D ON D.wh_id = B.idWH
WHERE
C.idItemProduk = A.item_id
AND B.TglTransaksi BETWEEN Datemin AND Datemax
(IF(Wh=0,'AND 1=1','AND D.wh_parn = 102'))
GROUP BY
C.idItemProduk
ORDER BY
jumlah DESC
) AS JML,
(
SELECT
SUM( C.qty ) AS qty
FROM
mob_penjualan B
LEFT JOIN mob_penjualandetail C ON C.noTransaksi = B.noTransaksi
LEFT JOIN krd_wh D ON D.wh_id = B.idWH
WHERE
C.idItemProduk = A.item_id
AND B.TglTransaksi BETWEEN Datemin AND Datemax
(IF(Wh=0,'AND 1=1','AND D.wh_parn = 102'))
GROUP BY
C.idItemProduk
ORDER BY
qty DESC
) AS QTY
FROM
krd_item A
ORDER BY
JML DESC, QTY DESC;
END
What's the solution?
WHERE C.idItemProduk = A.item_id
AND B.TglTransaksi BETWEEN Datemin AND Datemax
AND IF(Wh=0, 1, D.wh_parn = 102)
ER diagram
ER diagram is attached
I need to get sales invoice invoices.type = 'sales' and invoices.type = 'purchase'
with company name as you can see in select statement
also sales and purchase columns
My query
SELECT jobs.id as jobID,
-- c.name AS Customer,jobs.job_no,
invoices.invoice_due_date,
jobs.id,
( (invoice_items.amount * invoice_items.quantity * invoice_items.exchange_rate )) as Ammount
FROM invoices
INNER JOIN `invoice_items` ON invoices.id = invoice_items.invoice_id
INNER JOIN `jobs` ON jobs.id = invoices.job_id
-- INNER JOIN `company` as c ON c.company_id = jobs.company_id -- jobs and company.
WHERE invoices.type = 'sales'
-- new conditions
AND MONTH(jobs.created_at) = '3'
AND YEAR(jobs.created_at) = '2017'
AND jobs.status > 0
AND jobs.complete_job > 0
AND jobs.completed_at IS NOT NULL
AND invoice_items.deleted_at IS NULL
GROUP BY jobs.job_no
ORDER BY invoices.invoice_due_date DESC
Try this updated...
SELECT jobs.id as jobID,
C.name AS Customer,jobs.job_no,
invoices.invoice_due_date,
jobs.id,
( (invoice_items.amount * invoice_items.quantity *invoice_items.exchange_rate )) as Ammount,
CASE invoices.type
WHEN 'sales' THEN 'S'
ELSE 'P'
END as trans_type
FROM invoices
INNER JOIN `invoice_items` ON invoices.id = invoice_items.invoice_id
INNER JOIN `jobs` ON jobs.id = invoices.job_id
LEFT OUTER JOIN `company` as C ON C.company_id = jobs.company_id
WHERE (invoices.type = 'sales' OR invoices.type = 'purchase') AND (MONTH(jobs.created_at) = '3') AND (YEAR(jobs.created_at) = '2017') AND (jobs.status > 0) AND (jobs.complete_job > 0) AND (jobs.completed_at IS NOT NULL)
I have the below code.
There is one which is one part which is "ISNULL(PO101_EXT_COST, 0)*MM01.MM021_RATE AS Amount, "
I will like to change to a if else statement.
When "MM01.MM021_RATE" = '1' then PO101_EXT_COST * MM021_FOREIGN_RATE
When "MM01.MM021_RATE" is not = '1' then PO101_EXT_COST * MM021_RATE
How can i change my code below?
SELECT
CASE
When MM01.MM021_RATE = 1
Then ISNULL(PO101_EXT_COST, 0)*MM01.MM021_FOREIGN_RATE
Else ISNULL(PO101_EXT_COST, 0)*MM01.MM021_RATE
END AS Amt END AS Amount,
ISNULL(IN100_INV_CODE,'') AS [Item Code],
ISNULL(IN006_DESC,'') AS Major,
ISNULL(IN007_DESC,'') AS Minor,
ISNULL(IN100_DESC,'') AS Item,
ISNULL(PO100_PO_REQ, 0) AS [PO #],
ISNULL(PO100_EVT_ID, 0) AS [Ev ID],
ISNULL(EV200_EVT_DESC, '') AS [Ev Desc],
ISNULL(PO101_EXT_COST, 0) AS OriginalAmt,
ISNULL(PO101_PHASE, '') AS Phase,
ISNULL(PO101_STATUS, '') AS Status,
ISNULL(EV870_ACCT_SECURITY,'') AS [ARCtl],
ISNULL(PO102_ACCOUNT,'') AS [GL Account],
MM01.MM021_EFFECTIVE_DATE,
MM01.MM021_RATE,
MM01.MM021_FOREIGN_RATE,
(PO101_ORG_CODE) AS ORG,
(PO101_CURRENCY) AS Currency, (PO100_APPROVAL) AS Approval
FROM PO101_ORD_DTL
LEFT OUTER JOIN PO100_ORDERS ON
PO100_ORG_CODE = PO101_ORG_CODE AND
PO100_PO_REQ = PO101_PO_REQ
LEFT JOIN PO102_DISTR ON
PO102_ORG_CODE = PO101_ORG_CODE AND
PO102_PO_REQ = PO101_PO_REQ AND
PO102_PO_REQ_SEQ = PO101_ORD_SEQ
LEFT OUTER JOIN EV200_EVENT_MASTER ON
PO100_ORG_CODE = EV200_ORG_CODE AND
PO100_EVT_ID = EV200_EVT_ID
LEFT OUTER JOIN MM021_CURRENCY_RATES MM01 ON
PO101_CURRENCY = MM01.MM021_CODE
INNER JOIN
(SELECT MM021_CODE, MAX(MM021_EFFECTIVE_DATE) AS EFFECTIVE_DATE
FROM MM021_CURRENCY_RATES
WHERE MM021_FOREIGN_RATE > 0 AND MM021_TO_CODE = '***'
GROUP BY MM021_CODE) MM02 ON
MM01.MM021_CODE = MM02.MM021_CODE AND
MM01.MM021_EFFECTIVE_DATE = MM02.EFFECTIVE_DATE
LEFT OUTER JOIN IN100_INV_MASTER ON
PO101_ITEM = IN100_INV_CODE AND
PO101_ORG_CODE = IN100_ORG_CODE
LEFT OUTER JOIN IN007_MINOR_GROUP ON
IN100_ORG_CODE = IN007_ORG_CODE AND
IN100_MINOR = IN007_MINOR AND
IN100_MAJOR = IN007_MAJOR
LEFT JOIN IN006_MAJOR_GROUP ON
IN006_ORG_CODE = IN007_ORG_CODE AND
IN006_MAJOR = IN007_MAJOR
LEFT JOIN EV870_ACCT_MASTER ON
PO101_BILLTO=EV870_ACCT_CODE AND
PO101_ORG_CODE=EV870_ORG_CODE
WHERE
(PO101_ORG_CODE = '40' ) AND
(EV200_EVT_DESC = 'Tyrexpo India 2016') AND
(ISNULL(PO100_APPROVAL,'') IN ('A9')) AND
(ISNULL(PO101_STATUS, '') IN ('O','C','H')) AND
(ISNULL(PO101_PHASE, '') IN ('1')) AND
(PO101_TAX_RES_TYPE <> '8APGST')
Thanks!
/*
DROP TABLE A;
DROP TABLE B;
CREATE TEMPORARY TABLE A (ID INT, rateid int,cost int);
CREATE TEMPORARY TABLE B(ID INT,rate int,foreignrate int);
TRUNCATE TABLE A;
INSERT INTO A VALUES(1,1,1),(2,1,null),(3,2,3),(4,2,null),(5,0,null),(6,7,null) ,(7,1,null) ,(8,0,null) ;
TRUNCATE TABLE B;
INSERT INTO B VALUES(1,10,20),(2,30,40);
*/
#SELECT A.* FROM A;
#SELECT B.* FROM B;
SELECT A.*,
case
when B.id = 1 then
case
when A.cost is not null and B.foreignrate is not null then A.cost * B.foreignrate
else 0
end
when B.id is not null then
case
when A.cost is not null and B.rate is not null then A.ID * B.rate
else 0
end
else 0
END AS AMT
FROM A
LEFT OUTER join B on B.ID = A.rateid
I have two SQL queries that I would like to join into one:
select d.full_month, COUNT(*) amount
from fact_ticket t
join dim_queue q on t.queue_id = q.queue_id
join vt_scopes s on t.scope_id = s.scope_id
join dim_date d on t.create_date_id = d.date_id
where q.name = 'Support'
and year(GETDATE()) = YEAR(t.create_date)
and s.statusname not in ('discarded', 'closed')
group by d.full_month
order by 1;
and
select d.full_month, COUNT(*) amount
from fact_ticket t
join dim_queue q on t.queue_id = q.queue_id
join vt_scopes s on t.scope_id = s.scope_id
join dim_date d on t.create_date_id = d.date_id
where q.name = 'Support'
and year(GETDATE()) = YEAR(t.create_date)
and s.statusname in ('closed')
group by d.full_month
order by 1;
Both gives me now a result with a date column and an amount column, but I would like to get everything in one query where I would get date, amount 1, amount 2.
Is there an easy to do this?
You can use below query-
SELECT d.full_month,
COUNT(IF(s.statusname NOT IN ('discarded', 'closed'),1,NULL)) amount1,
COUNT(IF(s.statusname IN ('closed'),1,NULL)) amount2
FROM fact_ticket t
JOIN dim_queue q ON t.queue_id = q.queue_id
JOIN vt_scopes s ON t.scope_id = s.scope_id
JOIN dim_date d ON t.create_date_id = d.date_id
WHERE q.name = 'Support'
AND YEAR(GETDATE()) = YEAR(t.create_date)
GROUP BY d.full_month
ORDER BY 1;
2nd Edition: Even you can get benefit of index if exist on create_date by below query-
SELECT d.full_month,
COUNT(IF(s.statusname NOT IN ('discarded', 'closed'),1,NULL)) amount1,
COUNT(IF(s.statusname IN ('closed'),1,NULL)) amount2
FROM fact_ticket t
JOIN dim_queue q ON t.queue_id = q.queue_id
JOIN vt_scopes s ON t.scope_id = s.scope_id
JOIN dim_date d ON t.create_date_id = d.date_id
WHERE q.name = 'Support'
AND t.create_date>= DATE_FORMAT(NOW(),'%Y-01-01 00:00:00') AND t.create_date <= DATE_FORMAT(NOW(),'%Y-12-31 23:59:59');
GROUP BY d.full_month
ORDER BY 1;
Another way using sum function
SELECT
d.full_month,
SUM(s.statusname NOT IN ('discarded', 'closed')) amount,
SUM(s.statusname = 'closed') amount_closed
FROM
fact_ticket t
JOIN dim_queue q
ON t.queue_id = q.queue_id
JOIN vt_scopes s
ON t.scope_id = s.scope_id
JOIN dim_date d
ON t.create_date_id = d.date_id
WHERE q.name = 'Support'
AND YEAR(GETDATE ()) = YEAR(t.create_date)
GROUP BY d.full_month
ORDER BY 1 ;
We have a long sql procedure that takes limit & amount(limitCount) parameters. So, we are using concat statement for joining multiple queries. Calling this procedure gives err.no 1064 when we try to run it.
EDIT : Based on the comment, I'm adding the whole code.
CREATE PROCEDURE getProfileTasks (IN p_id1 INT, IN p_id2 INT , IN limitStart INT, IN limitCount INT)
BEGIN
SET #SQL = CONCAT('
SELECT P.access_type INTO #privacy FROM Profile P WHERE P.profile_id = ' , p_id2 , ';
IF( ' , p_id1, ' = ' ,p_id2 , ')
THEN
SELECT T.task_id, T.name, D.add_time, D.location, DATE_FORMAT(D.date1, "%d/%m/%y") as `date1`, D.time3, D.state, TIME_FORMAT(D.time1, "%H:%i")as `time1`, D.does_id, IFNULL(L.Like, 0) AS `LikeCount` , IFNULL(C.CommentCount,0) AS `CommentCount` FROM Task T
INNER JOIN Does D on D.task_id = T.task_id
INNER JOIN Profile P on P.profile_id = D.profile_id
LEFT OUTER JOIN (
SELECT D.does_id, COUNT(L.profile_id) as `Like` FROM `Likes` L
INNER JOIN Does D on D.does_id = L.does_id
INNER JOIN Profile P on P.profile_id = D.profile_id
WHERE P.profile_id = ' , p_id2 , '
GROUP BY does_id) L on L.does_id = D.does_id
LEFT OUTER JOIN( SELECT D.does_id, COUNT(C.content) AS `CommentCount` FROM Comment C
INNER JOIN Does D on D.does_id = C.does_id
GROUP BY (D.does_id)) C ON C.does_id = D.does_id
WHERE P.profile_id= ' , p_id2, ' ORDER BY D.add_time DESC LIMIT ' , limitStart , ', ' , limitCount, ';
ELSE
IF (#privacy = 0)
THEN
SELECT T.task_id, T.name, D.add_time, D.location, DATE_FORMAT(D.date1, "%d/%m/%y") as `date1`, D.time3, D.state, TIME_FORMAT(D.time1, "%H:%i")as `time1`, D.does_id, IFNULL(L.Like,0) AS `LikeCount`, IFNULL(C.CommentCount,0) AS `CommentCount` FROM Task T
INNER JOIN Does D on D.task_id = T.task_id
INNER JOIN Profile P on P.profile_id = D.profile_id
LEFT OUTER JOIN (
SELECT D.does_id, COUNT(L.profile_id) as `Like` FROM `Likes` L
INNER JOIN Does D on D.does_id = L.does_id
INNER JOIN Profile P on P.profile_id = D.profile_id
WHERE P.profile_id = ' , p_id2 , '
GROUP BY does_id) L on L.does_id = D.does_id
LEFT OUTER JOIN( SELECT D.does_id, COUNT(C.content) AS `CommentCount` FROM Comment C
INNER JOIN Does D on D.does_id = C.does_id
GROUP BY (D.does_id) )C ON C.does_id = D.does_id
WHERE P.profile_id= ' ,p_id2, ' ORDER BY D.add_time DESC LIMIT ' , limitStart , ', ' , limitCount, ';
ELSE
IF EXISTS ( SELECT * FROM Follows F
INNER JOIN Profile P on F.follower_id = P.profile_id
INNER JOIN Profile P2 on F.following_id = P2.profile_id
WHERE (P.profile_id = ' , p_id1, ' AND P2.profile_id = ' , p_id2 , '))
THEN
SELECT T.task_id, T.name, D.add_time, D.location, DATE_FORMAT(D.date1, "%d/%m/%y") as `date1`, D.time3, D.state, TIME_FORMAT(D.time1, "%H:%i")as `time1`, D.does_id, IFNULL(L.Like,0) AS `LikeCount`, IFNULL(C.CommentCount,0) AS `CommentCount` FROM Task T
INNER JOIN Does D on D.task_id = T.task_id
INNER JOIN Profile P on P.profile_id = D.profile_id
LEFT OUTER JOIN (
SELECT D.does_id, COUNT(L.profile_id) as `Like` FROM `Likes` L
INNER JOIN Does D on D.does_id = L.does_id
INNER JOIN Profile P on P.profile_id = D.profile_id
WHERE P.profile_id = ' , p_id2 , '
GROUP BY does_id) L on L.does_id = D.does_id
LEFT OUTER JOIN( SELECT D.does_id, COUNT(C.content) AS `CommentCount` FROM Comment C
INNER JOIN Does D on D.does_id = C.does_id
GROUP BY (D.does_id) )C ON C.does_id = D.does_id
WHERE P.profile_id= ' , p_id2 , ' ORDER BY D.add_time DESC LIMIT ' , limitStart , ', ' , limitCount, ';
END IF;
END IF;
END IF; '
);
PREPARE query FROM #SQL;
EXECUTE query;
DEALLOCATE PREPARE query;
END
Anyone has any idea about why we are getting this error ?
ERROR : #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 'IF( 18 = 18) THEN SELECT T.task_id, T.name, D.add_time, D.location, DATE_' at line 2
P.S : DELIMITER is set to //
Since the way the query in the stored procedure was created isn't really server-friendly (nor friendly to other developers) I have reformatted the stored procedure. Then I also noted that it's actually the same query that's executed in three cases, so there is a lot of duplication.
CREATE PROCEDURE getProfileTasks (IN p_id1 INT, IN p_id2 INT , IN limitStart INT, IN limitCount INT)
BEGIN
DECLARE privacy INT;
DECLARE is_following INT;
SELECT P.access_type INTO privacy FROM Profile P WHERE P.profile_id = p_id2;
SELECT COUNT(*) INTO is_following
FROM Follows F
INNER JOIN Profile P on F.follower_id = P.profile_id
INNER JOIN Profile P2 on F.following_id = P2.profile_id
WHERE (P.profile_id = p_id1 AND P2.profile_id = p_id2)
LIMIT 1;
IF ( (p_id1 = p_id2) OR (privacy = 0) OR (is_following > 0) )
THEN
-- Using CONCAT and prepared statement because LIMIT won't work otherwise
#SQL = CONCAT('
SELECT
T.task_id
, T.name
, D.add_time
, D.location
, DATE_FORMAT(D.date1, "%d/%m/%y") AS `date1`
, D.time3
, D.state
, TIME_FORMAT(D.time1, "%H:%i") AS `time1`
, D.does_id
, IFNULL(L.`Like`, 0) AS `LikeCount`
, IFNULL(C.CommentCount,0) AS `CommentCount`
FROM Task T
INNER JOIN Does D on D.task_id = T.task_id
INNER JOIN Profile P on P.profile_id = D.profile_id
LEFT OUTER JOIN (
SELECT D.does_id, COUNT(L.profile_id) AS `Like`
FROM `Likes` L
INNER JOIN Does D on D.does_id = L.does_id
INNER JOIN Profile P on P.profile_id = D.profile_id
WHERE P.profile_id = #p_id2
GROUP BY does_id
) L on L.does_id = D.does_id
LEFT OUTER JOIN (
SELECT D.does_id, COUNT(C.content) AS `CommentCount`
FROM Comment C
INNER JOIN Does D on D.does_id = C.does_id
GROUP BY (D.does_id)
) C ON C.does_id = D.does_id
WHERE P.profile_id= #p_id2
ORDER BY D.add_time DESC
LIMIT ', limitStart, ', ' , limitCount, ';');
SET #p_id2 = p_id2;
PREPARE query FROM #SQL;
EXECUTE query USING #p_id2;
DEALLOCATE PREPARE query;
END IF;
END
And I also added backticks around Like in IFNULL(L.`Like`, 0) AS `LikeCount`, because that's a potential problem as pointed out in the comments of the question.