I am trying to use #variable1 + #variable2 into a query but is actually given 0 as result.
MariaDB
Server Version: 10.2.21
set #start_at = '2019-01-01';
set #end_at = '2019-01-16';
set #receivable = 0;
set #invoiced = 0;
SELECT DISTINCT Customer.custnr 'Customer Number',
Address.name 'Name',
#receivable := sum(case
WHEN [condition1 <= #start_at]
AND Transactions.`key` not in [subquery]
THEN Transactions.amount
ELSE 0 END) 'Account Receivable',
#invoiced := sum(case
WHEN [condition1 between #start_at and #end_at]
AND [condition2]
AND [condition3]
AND Transactions.`key` not in [subquery]
THEN Transactions.amount
ELSE 0 END) 'Invoiced',
#receivable + #invoiced 'Total'
FROM LocalCust
INNER JOIN Customer
on Customer.`key` = LocalCust.customerkey
INNER JOIN Address
on Address.`key` = Customer.addresskey
INNER JOIN Location
on Location.`key` = LocalCust.localkey
INNER JOIN Transactions
on Transactions.localcustkey = LocalCust.`Key`
GROUP BY Transactions.localcustkey;
Result:
Use a subquery and don't use variables at all:
SELECT x.*, (Account_Receivable + Invoice) as Total
FROM (SELECT c.custnr as Customer_Number, a.name,
sum(case when condition1 <= #start_at and
t.`key` not in [subquery]
then t.amount
else 0
end) as Account_Receivable,
sum(case when condition1 between #start_at and #end_at and
[condition2] and
[condition3] and
t.`key` not in [subquery]
then t.amount
else 0
end) as Invoiced
FROM LocalCust lc JOIN
Customer c
on c.`key` = lc.customerkey JOIN
Address a
on a.`key` = c.addresskey JOIN
Location l
on l.`key` = lc.localkey join
Transactions t
on t.localcustkey = lc.`Key`
GROUP BY c.custnr, a.name
) x;
Notes:
Table aliases make the query easier to write and to read.
SELECT DISTINCT is almost never needed with GROUP BY.
The GROUP BY keys should match the unaggregated columns in the SELECT.
Choose column aliases that do not need to be escaped. That is, no spaces.
You can not just put #receivable, #invoiced and #receivable + #invoiced in the same select statement. (They will not store the value in order. They will be executed at the same time.)
First, You need to store the values in #receivable, #invoiced then use a subquery to calculate the total:
set #start_at = '2019-01-01';
set #end_at = '2019-01-16';
set #receivable = 0;
set #invoiced = 0;
SELECT *, A.[Account Receivable] + A.[Invoiced] AS TOTAL FROM (
SELECT DISTINCT Customer.custnr 'Customer Number',
Address.name 'Name',
#receivable := sum(case
WHEN [condition1 <= #start_at]
AND Transactions.`key` not in [subquery]
THEN Transactions.amount
ELSE 0 END) 'Account Receivable',
#invoiced := sum(case
WHEN [condition1 between #start_at and #end_at]
AND [condition2]
AND [condition3]
AND Transactions.`key` not in [subquery]
THEN Transactions.amount
ELSE 0 END) 'Invoiced'
FROM LocalCust
INNER JOIN Customer
on Customer.`key` = LocalCust.customerkey
INNER JOIN Address
on Address.`key` = Customer.addresskey
INNER JOIN Location
on Location.`key` = LocalCust.localkey
INNER JOIN Transactions
on Transactions.localcustkey = LocalCust.`Key`
GROUP BY Transactions.localcustkey) A;
Related
I have this query that is inside another one that calculates avg per month, but when this query doesn't return anything, then I have an empty table as a result, but I want it to be a 0 instead, I think this result is because of the group by
select
coalesce(count(distinct t.order_id),0) as ordenes,
'Erradas' as tipo,
EXTRACT(MONTH FROM o.order_creation_date) as mes
from (
select
orders.order_id,
pd.missing ,
pd.incomplete ,
pd.damaged,
pd.status_code ,
r.reason ,
r.reason_type,
(case
when ((pd.missing is null) and (pd.incomplete is null) and (pd.damaged is null))
then NULL
when ((r.reason_type not in ('F', 'W')) and
(((pd.missing + pd.incomplete) + pd.damaged) > 0)) then 1
when ((r.reason = 'F') and (pd.missing > 0)) then 1
when ((r.reason = 'W') and (pd.missing > 0)) then 0
else 0 end) AS refund_result
from module.orders
inner join module.pack p on orders.order_id = p.order_id
inner join module.pack_d pd on p.asn = pd.asn
left join module.reason r on r.reason = p.reason
INNER JOIN module.mv_reporte mc ON orders.customer_id = mc.rut
WHERE mc.level = 'VIP'
) t
inner join ecommerce.orders o on o.order_no = t.id
where refund_result = 1
and o.order_creation_date BETWEEN '2022/01/01' AND '2022/12/31'
group by month
order by month
As you can see, I tried to use coalesce, but it didn't work
I'm writing code for the production report.
I had written this query
SELECT
P.*,
(
SELECT
COUNT(id) AS cnt
FROM
bales
WHERE
create_date < '2019-11-01' AND product_id = P.id AND(TYPE = 'bale' OR TYPE = 'bag')
) AS before_prod,
(
SELECT
COUNT(id) AS cnt
FROM
bales
WHERE
(
dispatched = '0' OR disp_bunch = '0'
) AND dispatch_date < '2019-11-01' AND product_id = P.id AND(TYPE = 'bale' OR TYPE = 'bag')
) AS before_dispatched,
(
SELECT
COUNT(id) AS cnt
FROM
bales
WHERE
create_date BETWEEN '2019-11-01' AND '2019-11-06' AND product_id = P.id AND(TYPE = 'bale' OR TYPE = 'bag')
) AS production,
(
SELECT
COUNT(id) AS cnt
FROM
bales
WHERE
(
dispatched = '0' OR disp_bunch = '0'
) AND dispatch_date BETWEEN '2019-11-01' AND '2019-11-06' AND product_id = P.id AND(TYPE = 'bale' OR TYPE = 'bag')
) AS production_dispatched,
C.name AS category_name
FROM
products P
INNER JOIN category C ON
C.id = P.category
This query is working but as I have too many records in all tables it takes too much time.
also, I need only records where before_prod, before_dispatched, production, production_dispatched all these subquery results should be greater than 0.
I tried to use having clause but it also takes too much time.
I have also tried php for loop, * LOGIC: first all products than in for loop its production. but it was much slower.*
How can I optimize my query?
You can use join instead and select case to sum your data that matches your conditions.
select p.*, t.*
from products p
inner join (
select t2.id, sum(case when create_date < '2019-11-01' then 1 else 0 end) as before_prod
, sum(case when (dispatched = '0' or disp_bunch = '0') and create_date < '2019-11-01' then 1 else 0 end) as before_dispatched
, sum(case when create_date between '2019-11-01' and '2019-11-06' then 1 else 0 end) as production
, sum(case when (dispatched = '0' or disp_bunch = '0') and create_date between '2019-11-01' and '2019-11-06' then 1 else 0 end) as production_dispatched
from bales t1
inner join product t2 on t2.id= t1.product_id
inner join category t3 on t3.id = t2.category
where t1.TYPE in ('bale', 'bag')
group by t2.id) t
on t.id = p.id
I have this pseudo SQL code for what I want to achieve:
UPDATE orders o
SET o.datePaid = null
WHERE
(
SELECT SUM(amount)
FROM transactions t
WHERE t.orderId = o.id
AND t.status = 'success'
AND t.type = 'refund'
)
>=
(
SELECT SUM(amount)
FROM transactions t
WHERE t.orderId = o.id
AND t.status = 'success'
AND t.type IN ('purchase', 'capture')
)
How would I do this in SQL?
I think your approach is interesting. Here is a more concise method:
UPDATE orders o
SET o.datePaid = null
WHERE (SELECT SUM(CASE WHEN t.type = 'refund' THEN amount
WHEN t.type IN ('purchase', 'capture') THEN -amount
END)
FROM transactions t
WHERE t.orderId = o.id AND
t.status = 'success'
) > 0;
Your query works fine as is. However it can be more optimally written using MySQL multi-table UPDATE syntax:
UPDATE orders o
LEFT JOIN (SELECT orderId,
COALESCE(SUM(CASE WHEN type = 'refund' THEN amount END), 0) AS refunds,
COALESCE(SUM(CASE WHEN type IN ('purchase', 'capture') THEN amount END), 0) AS pc
FROM transactions
WHERE status = 'success'
GROUP BY orderId) t ON t.orderId = o.id
SET o.datePaid = NULL
WHERE t.refunds > t.pc
Demo on dbfiddle (includes your query working as well)
Your code would probably work just as it is. Give it a try.
You could also optimize the query to avoid the need for two subqueries by using a JOIN and conditional aggregation in a single subquery:
UPDATE orders o
INNER JOIN (
SELECT orderId
FROM transactions
WHERE
status = 'success'
AND type IN ('success', 'purchase', 'capture') -- this condition might be superfuous
GROUP BY o.id
HAVING
SUM(CASE WHEN type = 'success' THEN amount ELSE 0 END)
>= SUM(CASE WHEN type IN ('purchase', 'capture') THEN amount ELSE 0 END)
) t ON t.orderId = o.id
SET o.datePaid = null
Note: WHERE condition AND type IN ('success', 'purchase', 'capture') is superfluous if that list of 3 values represents all the possible values.
Trying to add another column with a new table, would appreciate any help/suggestions!
Current query:
SELECT parent.name AS parentname, a.name AS accname,
parent.code AS parentcode, a.code AS acccode,
parent.guid AS parentguid, a.guid AS accguid,
a.account_type AS accttype,
sum(case when date_format(post_date, '%Y-%m-%d') <= '2017-12-31' then (s.value_num/s.value_denom) else '0' end) AS 'value2017-12-31',
sum(case when date_format(post_date, '%Y-%m-%d') <= '2018-01-25' then (s.value_num/s.value_denom) else '0' end) AS 'value2018-01-25'
FROM transactions AS t INNER JOIN splits AS s ON s.tx_guid = t.guid
INNER JOIN accounts AS a ON a.guid = s.account_guid
INNER JOIN accounts AS parent ON parent.guid = a.parent_guid
WHERE a.hidden = 0 AND a.account_type NOT IN ('INCOME', 'EXPENSE')
AND parent.name <>''
AND a.guid = '3f3fc442a98225f481bb72e0fd526cbb'
GROUP by accname, parentname ORDER by acccode
And that works fine, gives 1 row of results. I'd now like to add another column to the results, I believe a left outer join from the prices table of the record that is the closest date before 2017-12-31. My attempt:
SELECT parent.name AS parentname, a.name AS accname,
parent.code AS parentcode, a.code AS acccode,
parent.guid AS parentguid, a.guid AS accguid,
a.account_type AS accttype,
sum(case when date_format(post_date, '%Y-%m-%d') <= '2017-12-31' then (s.value_num/s.value_denom) else '0' end) AS 'value2017-12-31',
sum(case when date_format(post_date, '%Y-%m-%d') <= '2018-01-25' then (s.value_num/s.value_denom) else '0' end) AS 'value2018-01-25',
MAX(case when date_format(p.date, '%Y-%m-%d') <= '2017-12-31' then (p.value_num/p.value_denom) else '0' end) AS 'price2017-12-31'
FROM transactions AS t INNER JOIN splits AS s ON s.tx_guid = t.guid
INNER JOIN accounts AS a ON a.guid = s.account_guid
INNER JOIN accounts AS parent ON parent.guid = a.parent_guid
LEFT OUTER JOIN prices as p ON p.commodity_guid = a.commodity_guid
WHERE a.hidden = 0 AND a.account_type NOT IN ('INCOME', 'EXPENSE')
AND parent.name <>''
AND a.guid = '3f3fc442a98225f481bb72e0fd526cbb'
GROUP by accname, parentname ORDER by acccode
It's obviously incorrect as it's now changing the values of value2017-12-31 and value2018-01-25. I get the price correctly using a separate query:
SELECT p.value_num/p.value_denom as calcprice
FROM `prices` as p
WHERE commodity_guid = '77be249d12d9889e90f08dde7c671eb0'
AND date_format(p.date, '%Y-%m-%d') <= '2017-12-31'
order
by date DESC
limit 1
Is there any way to combine them rather than using temp tables?
query taking 1 minute to fetch results
SELECT
`jp`.`id`,
`jp`.`title` AS game_title,
`jp`.`game_type`,
`jp`.`state_abb` AS game_state,
`jp`.`location` AS game_city,
`jp`.`zipcode` AS game_zipcode,
`jp`.`modified_on`,
`jp`.`posted_on`,
`jp`.`game_referal_amount`,
`jp`.`games_referal_amount_type`,
`jp`.`status`,
`jp`.`is_flaged`,
`u`.`id` AS employer_id,
`u`.`email` AS employer_email,
`u`.`name` AS employer_name,
`jf`.`name` AS game_function,
`jp`.`game_freeze_status`,
`jp`.`game_statistics`,
`jp`.`ats_value`,
`jp`.`integration_id`,
`u`.`account_manager_id`,
`jp`.`model_game`,
`jp`.`group_id`,
(CASE
WHEN jp.group_id != '0' THEN gm.group_name
ELSE 'NA'
END) AS group_name,
`jp`.`priority_game`,
(CASE
WHEN jp.country != 'US' THEN jp.country_name
ELSE ''
END) AS game_country,
IFNULL((CASE
WHEN
`jp`.`account_manager_id` IS NULL
OR `jp`.`account_manager_id` = 0
THEN
(SELECT
(CASE
WHEN
account_manager_id IS NULL
OR account_manager_id = 0
THEN
`u`.`account_manager_id`
ELSE account_manager_id
END) AS account_manager_id
FROM
user_user
WHERE
id = (SELECT
user_id
FROM
game_user_assigned
WHERE
game_id = `jp`.`id`
LIMIT 1))
ELSE `jp`.`account_manager_id`
END),
`u`.`account_manager_id`) AS acc,
(SELECT
COUNT(recach_limit_id)
FROM
recach_limit
WHERE
recach_limit = '1'
AND recach_limit_game_id = rpr.recach_limit_game_id) AS somewhatgame,
(SELECT
COUNT(recach_limit_id)
FROM
recach_limit
WHERE
recach_limit = '2'
AND recach_limit_game_id = rpr.recach_limit_game_id) AS verygamecommitted,
(SELECT
COUNT(recach_limit_id)
FROM
recach_limit
WHERE
recach_limit = '3'
AND recach_limit_game_id = rpr.recach_limit_game_id) AS notgame,
(SELECT
COUNT(joa.id) AS applicationcount
FROM
game_refer_to_member jrmm
INNER JOIN
game_refer jrr ON jrr.id = jrmm.rid
INNER JOIN
game_applied joa ON jrmm.id = joa.referred_by
WHERE
jrmm.STATUS = '1'
AND jrr.referby_user_id IN (SELECT
ab_testing_user_id
FROM
ab_testing)
AND joa.game_post_id = rpr.recach_limit_game_id
AND (rpr.recach_limit = 1
OR rpr.recach_limit = 2)) AS gamecount
FROM
(`game_post` AS jp)
JOIN
`user_info` AS u ON `jp`.`user_user_id` = `u`.`id`
JOIN
`game_functional` jf ON `jp`.`game_functional_id` = `jf`.`id`
LEFT JOIN
`group_musesm` gm ON `gm`.`group_id` = `jp`.`group_id`
LEFT JOIN
`recach_limit` rpr ON `jp`.`id` = `rpr`.`recach_limit_game_id`
WHERE
`jp`.`status` != '3'
GROUP BY `jp`.`id`
ORDER BY `posted_on` DESC
LIMIT 10
I would first suggest not nesting select statements because this will cause an n^x performance hit on every xth level and I see at least 3 levels of selects inside this query.
Add index
INDEX(status, posted_on)
Move LIMIT inside
Then, instead of saying
FROM (`game_post` AS jp)
say
FROM ( SELECT id FROM game_post
WHERE status != 3
ORDER BY posted_on DESC
LIMIT 10 ) AS ids
JOIN game_post AS jp USING(id)
(I am assuming that the PK of jp is (id)?)
That should efficiently use the new index to get the 10 ids needed. Then it will reach back into game_post to get the other columns.
LEFT
Also, don't say LEFT unless you need it. It costs something to generate NULLs that you may not be needing.
Is GROUP BY necessary?
If you remove the GROUP BY, does it show dup ids? The above changes may have eliminated the need.
IN(SELECT) may optimize poorly
Change
AND jrr.referby_user_id IN ( SELECT ab_testing_user_id
FROM ab_testing )
to
AND EXISTS ( SELECT * FROM ab_testing
WHERE ab_testing_user_id = jrr.referby_user_id )
(This change may or may not help, depending on the version you are running.)
More
Please provide EXPLAIN SELECT if you need further assistance.