This query takes around 45s to 1 min for 25000 records.I need an alternative to case
condition for expirydate field
SELECT a.id,
a.name,
a.lastname,
a.plainpass,
a.email,
a.custom_usertype,
a.custom_registertype,
a.content_state,
a.year,
a.bflag,
a.block,
a.trail_expiry,
a.subscribe_date,
CASE a.custom_usertype
WHEN (5)
THEN
(IF(
(SELECT custom_usertype
FROM skw_users
WHERE id = a.parent_id AND custom_usertype = 11) = 11
AND a.custom_registertype = "subscribed",
(SELECT DATE_FORMAT(prod.expiry_date, "%Y-%m-%d")
FROM skw_product prod
WHERE prod.student_id = a.id
ORDER BY prod.expiry_date DESC
LIMIT 1),
IF(
(SELECT custom_usertype
FROM skw_users
WHERE id = a.parent_id AND custom_usertype = 10) =
10
AND a.custom_registertype = "subscribed",
(SELECT DATE_FORMAT(prod.expiry_date, "%Y-%m-%d")
FROM skw_product prod
WHERE prod.User_id = a.parent_id
ORDER BY prod.expiry_date DESC
LIMIT 1),
(SELECT DATE_FORMAT(trail_expiry, "%Y-%m-%d")
FROM skw_users
WHERE id = a.parent_id))))
WHEN (3)
THEN
(IF(a.custom_registertype = "subscribed",
(SELECT DATE_FORMAT(prod.expiry_date, "%Y-%m-%d")
FROM skw_product prod
WHERE prod.User_id = a.parent_id
ORDER BY prod.expiry_date DESC
LIMIT 1),
(SELECT DATE_FORMAT(trail_expiry, "%Y-%m-%d")
FROM skw_users
WHERE id = a.parent_id)))
ELSE
(IF(a.custom_registertype = "subscribed",
(SELECT DATE_FORMAT(prod.expiry_date, "%Y-%m-%d")
FROM skw_product prod
WHERE prod.User_id = a.id
ORDER BY prod.expiry_date DESC
LIMIT 1),
(SELECT DATE_FORMAT(trail_expiry, "%Y-%m-%d")
FROM skw_users
WHERE id = a.id)))
END
AS expiry_date_n,
CASE a.custom_usertype
WHEN (5)
THEN
(SELECT TRIM(NAME)
FROM skw_users
WHERE id = a.parent_id AND custom_usertype = 10)
WHEN (3)
THEN
(SELECT TRIM(NAME)
FROM skw_users
WHERE id = a.parent_id)
WHEN (10)
THEN
(SELECT TRIM(NAME)
FROM skw_users
WHERE id = a.id AND a.custom_usertype = 10)
END
AS schoolname
FROM `skw_users` AS a
INNER JOIN
skw_user_usergroup_map AS map2
ON map2.user_id = a.id
WHERE map2.group_id = 2
GROUP BY a.id
ORDER BY trim(a.name) ASC
This query takes around 45s to 1 min for 25000 records.I need an alternative to case
condition for expirydate field
Try adding index on Primary Key column that is a.id and the column on which you are applying case that is a.custom_usertype
Hope this will speed up the execution of query :)
Related
Was wondering if there is a way to get the sum of the stock_case column for items with the same date_of_export ?
Updated with fiddle here and some relevant data:
https://www.db-fiddle.com/f/szC1Ftj3ZGEC24gSYp6ad4/4
The expected output would be this:
This is the query used
SELECT
st.product_code,
st.date_of_export,
st.best_before_date,
st.stock_case,
(
SELECT
SUM(st2.stock_case)
FROM
stock_tracking AS st2
WHERE
st2.product_code IN ('MGN003')
AND MONTH(st2.date_of_export) IN (07)
AND YEAR(st2.date_of_export) IN (2018)
AND st2.stock_case != 0
) AS total
FROM
stock_tracking st
WHERE
product_code IN ('MGN003')
AND MONTH(st.date_of_export) IN (07)
AND YEAR(st.date_of_export) IN (2018)
AND stock_case != 0
and my results
Would like to have a total column like 16, 16, 16, ... , 19, etc
For another case I used a subquery like so
SELECT
d.products_name,
stock_case,
st.date_of_export,
st.best_before_date,
st.product_code,
(SELECT
SUM(st2.stock_case)
FROM
stock_tracking AS st2
WHERE
DATE(st2.date_of_export) = (SELECT
DATE(tmp.last_update)
FROM
(SELECT
date_of_export AS last_update
FROM
stock_tracking
ORDER BY date_of_export DESC
LIMIT 1) AS tmp
WHERE
product_code = 'MGN003')) AS total
FROM
stock_tracking st
LEFT JOIN
products AS p ON p.products_model = st.product_code
LEFT JOIN
products_description AS d ON d.products_id = p.products_id
WHERE
product_code = 'MGN003'
AND d.language_id = 2
AND DATE(st.date_of_export) = (SELECT
DATE(tmp.last_update)
FROM
(SELECT
date_of_export AS last_update
FROM
stock_tracking AS st
ORDER BY date_of_export DESC
LIMIT 1) AS tmp)
with this result:
You can write a subquery to sum(stock_case) by date_of_export, then self join on Date, then you can get your expect result.
SELECT
s.product_name,
s.date_of_export,
s.best_before_date,
s.product_code,
s.stock_case,
t.totle
FROM
stock_tracking s
INNER JOIN
(
SELECT SUM(stock_case) totle,date_of_export dt
FROM stock_tracking
where
product_code = 'MGN003'
AND MONTH(date_of_export) =07
AND YEAR(date_of_export) =2018
AND stock_case != 0
GROUP BY date_of_export
) t on DATE_FORMAT(s.date_of_export, "%d-%m-%Y") = DATE_FORMAT(t.dt, "%d-%m-%Y")
where
s.product_code = 'MGN003'
AND MONTH(s.date_of_export) =07
AND YEAR(s.date_of_export) =2018
AND s.stock_case != 0
sqlfiddle
Without giving you the exact answer: You should think in the direction of:
SELECT SUM(column) FROM table WHERE ... GROUP BY date
or
SELECT SUM(column), DISTINCT date FROM table WHERE ...
So lookup the way GROUP BY and DISTINCT work :-)
I know I can do this:
IF( 2 = 2 AND 0 = 0, 1, 0 ) AS some_result,
(outputs 1 of course)
But I have the some inner selects in my query like so:
(select ... ) as innerA,
(select ... ) as innerB,
(select ... ) as innerC,
I then would like to do something like:
IF( innerA, innerB, innerC ) AS my_result, (if innerA then use innerB, otherwise innerC)
But I get the error Unknown column 'innerA' in 'field list' which makes sense because it isn't a column.
How can I use my aliases innerA, innerB and innerC to generate my_result?
EDIT:
In an attempt to explain what I mean, here is the relevant part of the query:
(select t.id from transaction t where loan_id = l.id and status_id = 61) as chargeback_transaction_id,
(select t.`datestamp` from transaction t where loan_id = l.id and status_id = 61) as chargeback_transaction_id_date,
(select ls.`datestamp` from loan_status ls where loan_id = l.id and status_id = 16 and datestamp < chargeback_transaction_id_date ORDER BY datestamp DESC LIMIT 1) as loan_closed_transaction_id_date_before_the_chargeback_aka_status_16,
/* Get date of next status 9, after the first 16: */
(select ls.`datestamp` from loan_status ls where loan_id = l.id and status_id = 9 and datestamp > loan_closed_transaction_id_date_before_the_chargeback_aka_status_16 ORDER BY datestamp ASC LIMIT 1) as date_of_next_status_9_after_the_first_16,
(select ls2.`datestamp` from loan_status ls2 INNER JOIN client clj ON (clj.`client_id` = ls2.`loan_id`) where clj.client_id = '3378228' and loan_id != l.id and ls2.status_id = 9 and datestamp > loan_closed_transaction_id_date_before_the_chargeback_aka_status_16 and datestamp < date_of_next_status_9_after_the_first_16 LIMIT 1) as other_loan_datestamp,
IF( other_loan_datestamp, loan_closed_transaction_id_date_before_the_chargeback_aka_status_16, date_of_next_status_9_after_the_first_16 ) AS close_date_to_use,
I guess this last part (IF( other_loan_datestamp,) is just completely meaningless but is there a way to do such 'if else' logic with aliases in MySQL?
Note:
other_loan_datestamp, loan_closed_transaction_id_date_before_the_chargeback_aka_status_16 and date_of_next_status_9_after_the_first_16 are dates like 2018-05-25 12:31:16
You can't use alias in this case. You, unfortunately, will have to write the whole thing. Another way is to wrap it in subquery.
SELECT a.*
, IF( a.other_loan_datestamp, a.loan_closed_transaction_id_date_before_the_chargeback_aka_status_16, a.date_of_next_status_9_after_the_first_16 ) AS close_date_to_use
FROM (
(select t.id from transaction t where loan_id = l.id and status_id = 61) as chargeback_transaction_id,
(select t.`datestamp` from transaction t where loan_id = l.id and status_id = 61) as chargeback_transaction_id_date,
(select ls.`datestamp` from loan_status ls where loan_id = l.id and status_id = 16 and datestamp < chargeback_transaction_id_date ORDER BY datestamp DESC LIMIT 1) as loan_closed_transaction_id_date_before_the_chargeback_aka_status_16,
/* Get date of next status 9, after the first 16: */
(select ls.`datestamp` from loan_status ls where loan_id = l.id and status_id = 9 and datestamp > loan_closed_transaction_id_date_before_the_chargeback_aka_status_16 ORDER BY datestamp ASC LIMIT 1) as date_of_next_status_9_after_the_first_16,
(select ls2.`datestamp` from loan_status ls2 INNER JOIN client clj ON (clj.`client_id` = ls2.`loan_id`) where clj.client_id = '3378228' and loan_id != l.id and ls2.status_id = 9 and datestamp > loan_closed_transaction_id_date_before_the_chargeback_aka_status_16 and datestamp < date_of_next_status_9_after_the_first_16 LIMIT 1) as other_loan_datestamp
) a
You got an idea
select if( i1.v, i2.v, i3.v ) as some_result
from (select 0 as v) i1, (select 2 as v) i2, (select 3 as v) i3
I am trying to collaborate 3 queries to perform arithmetic operation. The queries are shown in
(SELECT ITEM_ID,ISNULL(SUM(REC_GOOD_QTY),0)
FROM INVENTORY_ITEM
WHERE COMPANY_ID = 1
AND INVENTORY_ITEM.COMPANY_BRANCH_ID = 1
AND INVENTORY_ITEM.INV_ITEM_STATUS = 'Inward'
AND GRN_DATE < CAST('2017-01-10 00:00:00.0' AS DATETIME)
GROUP BY INVENTORY_ITEM.ITEM_ID) -
(SELECT ITEM_ID, SUM ( TOTAL_LITRE )
FROM STOCK_REQUISITION_ITEM B, STOCK_REQUISITION A
WHERE A.ID = B.REQUISITION_ID
AND A.COMPANY_ID = 1
AND A.REQ_FROM_BRANCH_ID = 1
AND A.REQUISITION_DATE < CAST('2017-01-10 00:00:00.0' AS DATETIME)
GROUP BY B.ITEM_ID) +
(SELECT ITEM_ID, SUM ( RETURN_QUANTITY )
FROM STOCK_RETURN_ITEM B, STOCK_RETURN A
WHERE A.ID = B.STOCK_RETURN_ID
AND A.COMPANY_ID = 1
AND A.COMPANY_BRANCH_ID = 1
AND A.RETURN_DATE <= CAST('2017-01-10 00:00:00.0' AS DATETIME)
GROUP BY B.ITEM_ID)
I am getting this error.
[Err] 42000 - [SQL Server]Incorrect syntax near '-'.
42000 - [SQL Server]Incorrect syntax near '+'
Not much to go on here for details. And we aren't actually sure if you are using mysql or sql server but pretty sure you are using sql server. I think you can accomplish what you are trying to do with something along these lines.
with Iventory as
(
SELECT i.ITEM_ID
, GoodQty = ISNULL(SUM(i.REC_GOOD_QTY), 0)
FROM INVENTORY_ITEM i
WHERE COMPANY_ID = 1
AND i.COMPANY_BRANCH_ID = 1
AND i.INV_ITEM_STATUS = 'Inward'
AND i.GRN_DATE < '2017-01-10'
GROUP BY i.ITEM_ID
)
, StockRequisition as
(
SELECT ITEM_ID
, TotalLitre = SUM(TOTAL_LITRE)
FROM STOCK_REQUISITION_ITEM B
JOIN STOCK_REQUISITION A ON A.ID = B.REQUISITION_ID
WHERE A.COMPANY_ID = 1
AND A.REQ_FROM_BRANCH_ID = 1
AND A.REQUISITION_DATE < '2017-01-10'
GROUP BY B.ITEM_ID
)
StockReturn as
(
SELECT ITEM_ID
, ReturnQuantity = SUM(RETURN_QUANTITY)
FROM STOCK_RETURN_ITEM B
JOIN STOCK_RETURN A ON A.ID = B.STOCK_RETURN_ID
WHERE A.COMPANY_ID = 1
AND A.COMPANY_BRANCH_ID = 1
AND A.RETURN_DATE <= '2017-01-10'
GROUP BY B.ITEM_ID
)
select i.ITEM_ID
, MyCalculation = i.GoodQty - isnull(Req.TotalLitre, 0) + isnull(sr.ReturnQuantity, 0)
from Inventory i
left join StockRequisition sr on sr.ITEM_ID = i.ITEM_ID
left join StockReturn Req on Req.ITEM_ID = i.ITEM_ID
In your queries you always returns two fields ITEM_ID and a numeric field.
To apply an arithmetical operation you must return one numeric field
The first query:
SELECT ITEM_ID,ISNULL(SUM(REC_GOOD_QTY),0)
becomes
SELECT ISNULL(SUM(REC_GOOD_QTY),0)
The second query:
SELECT ITEM_ID, SUM ( TOTAL_LITRE )
becomes
SELECT SUM ( TOTAL_LITRE )
The third query:
SELECT ITEM_ID, SUM ( RETURN_QUANTITY )
becomes
SELECT SUM ( RETURN_QUANTITY )
So the GROUP BY returns more than one row per query
UPDATE
i try to rewrite your query:
SELECT DISTINCT ii.item_id,
ISNULL(
(SELECT SUM(ii2.rec_good_qty)
FROM inventory_item ii2
WHERE ii2.item_id = ii.item_id
AND ii.company_id = 1
AND ii.company_branch_id = 1
AND ii.inv_item_status = 'Inward'
AND ii.grn_date < CAST('2017-01-10 00:00:00.0' AS DATETIME))
,0) -
ISNULL(
(SELECT SUM(total_litre)
FROM stock_requisition_item b
JOIN stock_requisition a
ON a.id = b.requisition_id
WHERE a.company_id = 1
AND a.req_from_branch_id = 1
AND a.requisition_date < CAST('2017-01-10 00:00:00.0' AS DATETIME))
,0) +
ISNULL(
(SELECT SUM(return_quantity)
FROM stock_return_item b
JOIN stock_return a
ON a.id = b.stock_return_id
WHERE a.company_id = 1
AND a.company_branch_id = 1
AND a.return_date <= CAST('2017-01-10 00:00:00.0' AS DATETIME))
,0) AS result
FROM inventory_item ii
WHERE ii.company_id = 1
AND ii.company_branch_id = 1
AND ii.inv_item_status = 'Inward'
AND ii.grn_date < CAST('2017-01-10 00:00:00.0' AS DATETIME)
I have this query:
SELECT
sec_to_time(avg(t1.sessiontime)) as aloc,
CONCAT(TRUNCATE(sum(t1.terminatecauseid = 1) * 100 / count(*),
1),
'%') as asr,
count(*) as calls,
cast(t1.destination as unsigned) as prefix,
t2.destination as destination,
SEC_TO_TIME(sum(t1.sessiontime)) as duration
FROM
cc_call AS t1
inner join
cc_prefix as t2 ON t1.destination = t2.prefix
WHERE
t1.card_id = '133' AND t1.starttime >= ('2014-06-1') AND t1.starttime <= ('2014-07-01 23:59:59') and t1.terminatecauseid = 1
group by t1.destination
order by duration DESC
LIMIT 0 , 25
t1.terminatecauseid = 1 means successful call,
'asr' means average success rate,
Im trying to find out how many calls with (t1.terminatecauseid = 1) from the total calls made to an extension.
this line doesn't work:
sum(t1.terminatecauseid = 1) * 100 / count(*)
since I already have (t1.terminatecauseid = 1) in the WHERE clause.
Im thinking about putting a subquery, to retrieve total calls, where count(*) currently is.
How can I have this query calculate the ASR with total calls made?
example sqlfiddle
if possible, I'd like to not show results with duration=NULL
Use conditional aggregation, something like this:
SELECT sec_to_time(avg(case when t1.terminatecauseid = 1 then t1.sessiontime end)) as aloc,
CONCAT(TRUNCATE(sum(t1.terminatecauseid = 1) * 100 / count(*),
1),
'%') as asr,
count(*) as TotalCalls,
sum(t1.terminatecauseid = 1) as Terminated1Calls,
cast(t1.destination as unsigned) as prefix,
t2.destination as destination,
SEC_TO_TIME(sum(case when t1.terminatecauseid = 1 then t1.sessiontime end)) as duration
FROM cc_call t1 inner join
cc_prefix t2
ON t1.destination = t2.prefix
WHERE t1.card_id = '133' AND
t1.starttime >= ('2014-06-1') AND t1.starttime <= ('2014-07-01 23:59:59')
group by t1.destination
order by duration DESC
LIMIT 0 , 25;
I have this query and it's very slow. Can i write this query in other way by avoiding subselects for example?
Also i tried adding composite index on
MyIndex(kategorije_id,izdvojen,izdvojen_kad,datum)
but it doesent use it when i explain this query so is there another index that i can use to speed up this query?
SELECT artikli.datum AS brojx, artikli.izdvojen AS i, artikli.izdvojen_kad AS ii, artikli.name
FROM artikli
WHERE artikli.izbrisan =0
AND artikli.prodano !=3
AND artikli.zavrseno =0
AND artikli.od_id !=0
AND kategorije_id
IN ( 18 )
AND (
SELECT count( * )
FROM artikli_polja, polja
WHERE polja.id_kat = artikli.kategorije_id
AND artikli_polja.id_polja = polja.id
AND artikli_polja.id_artikal = artikli.id
AND polja.name = "godiste"
AND artikli_polja.valueInt >= "1993"
) >0
AND (
SELECT count( * )
FROM artikli_polja, polja
WHERE polja.id_kat = artikli.kategorije_id
AND artikli_polja.id_polja = polja.id
AND artikli_polja.id_artikal = artikli.id
AND polja.name = "godiste"
AND artikli_polja.valueInt <= "2000"
) >0
ORDER BY i DESC , ii DESC , brojx DESC
LIMIT 140 , 35
Try this query:
SELECT a.datum AS brojx, a.izdvojen AS i, a.izdvojen_kad AS ii, a.name
FROM artikli a
WHERE a.izbrisan =0
AND a.prodano !=3
AND a.zavrseno =0
AND a.od_id !=0
AND a.kategorije_id = 18
AND EXISTS
(select 'X'
from artikli_polja ap,
JOIN polja p
ON ap.id_polja = p.id AND p.id_kat = a.kategorije_id
AND ap.id_artikal = a.id
AND p.name = 'godiste'
AND ap.valueInt >= 1993 AND ap.valueInt <= 2000
);
Please check.
Try this query -
SELECT a.datum AS brojx, a.izdvojen AS i, a.izdvojen_kad AS ii, a.name FROM artikli a
JOIN artikli_polja ap
ON ap.id_artikal = a.id
JOIN polja p
ON ap.id_polja = p.id AND p.id_kat = a.kategorije_id
WHERE
a.izbrisan =0
AND a.prodano !=3
AND a.zavrseno =0
AND a.od_id !=0
AND kategorije_id = 18
AND p.name = 'godiste'
AND ap.valueInt >= 1993 AND ap.valueInt <= 2000;
I have removed ORDER BY and LIMIT clauses from the query; try to work out this query firstly.