MySQL: Using alias in select arithmetic - Unknown field - mysql

Here's my select:
SELECT
SUM(t.amount + c.designFeeValue) as cashReceived,
ROUND(SUM(i.value) * (m.percentOurs / 100)) as adValue,
m.managementFee as managementFee,
m.productionCost as productionCost,
5 as emailAddress,
(
(
SELECT value
FROM commission_transactions
WHERE isDebit IS
TRUE
) -
(
SELECT value
FROM commission_transactions
WHERE isDebit IS
FALSE
)
) as miscExpenses,
(managementFee + productionCost + emailAddress + miscExpenses) as totalExpenses
This is bombing because of the following line, where I add up some aliases.
(managementFee + productionCost + emailAddress + miscExpenses) as totalExpenses
The aliases are unknown fields.
Is there a way I can keep the aliases for this arithmetic or do I need to re-do all the math that generates each alias for the calculation of totalExpenses? That seems like a very ugly way to do it.
UPDATE:
Per your suggestions, I am now using a derived table.
SELECT
cashReceived,
adValue,
managementFee,
productionCost,
emailAddress,
miscExpenses,
adValue + managementFee + productionCost + emailAddress + miscExpenses as totalExpenses
FROM (
SELECT
SUM(t.amount + c.designFeeValue) as cashReceived,
ROUND(SUM(i.value) * (m.percentOurs / 100)) as adValue,
m.managementFee as managementFee,
m.productionCost as productionCost,
5 as emailAddress,
(
(
SELECT value
FROM commission_transactions
WHERE isDebit IS TRUE
) -
(
SELECT value
FROM commission_transactions
WHERE isDebit IS FALSE
)
) as miscExpenses
FROM magazines m
JOIN insertions i ON i.magazineId = m.id
JOIN transactions t ON t.insertionId = i.id
JOIN contracts c ON i.contractId = c.id
JOIN commission_transactions ct ON m.id = ct.magazineId
WHERE m.id = 17
AND t.isChargedBack IS FALSE
AND t.`timestamp` >= '2013-08-01 00:00:00'
AND t.`timestamp` < '2013-09-01 00:00:00'
AND ct.createdDate >= '2013-08-01 00:00:00'
AND ct.createdDate < '2013-09-01 00:00:00'
) sub;

Aliases aren't available for re-use within the field list, e.g:
mysql> select 5 as five, five + 1 as six;
ERROR 1054 (42S22): Unknown column 'five' in 'field list'
You'll have to wrap the select with another one, then do your alias math in that wrapper, e.g.
select *, managementFee + productionCost + emailAddress + miscExpenses) as totalExpenses
FROM (
... your above query here ...
)

Related

MySQL duration for 9 rows, that's my code

SELECT DATE_FORMAT(b.checktime,"%Y-%m-%d") AS dtDate,
case when (
SELECT DATE_FORMAT(a.checktime,'%H:%i:%s')
FROM checkinout a
WHERE a.checktype='0'
and a.userid=1
and DATE_FORMAT(a.checktime,'%Y-%m-%d')=DATE_FORMAT(b.checktime,'%Y-%m-%d')
LIMIT 1)
is not NULL
then
(
SELECT
DATE_FORMAT(a.checktime,'%H:%i:%s')
FROM checkinout a
WHERE a.checktype='0'
and a.userid=1
and DATE_FORMAT(a.checktime,'%Y-%m-%d')=DATE_FORMAT(b.checktime,'%Y-%m-%d')
LIMIT 1
)
else 'N/A' END
AS Chkin
from checkinout b
where
DATE_FORMAT(b.checktime,"%m")='06' AND
DATE_FORMAT(b.checktime,"%Y")='2019' AND
DATE_FORMAT(b.checktime,"%w")!='0' AND .
DATE_FORMAT(b.checktime,"%w")!='6' AND .
DATE_FORMAT(b.checktime,"%Y-%m-%d") not in
(select date_s from wend)
GROUP BY dtDate
ORDER BY dtDate DESC
Affected rows: 0 Found rows: 9 Warnings: 0 Duration for 1 query: 25.665 sec.
what's wrong with this query, for 9 rows need 25.665 seconds
Thanks
Without understanding the purpose of the query, it can be rewritten to:
SELECT DISTINCT date(b.checktime) AS dtDate,
coalesce((
SELECT time(a.checktime)
FROM checkinout a
WHERE a.checktype = '0'
and a.userid = 1
and date(a.checktime) = date(b.checktime)
LIMIT 1
), 'N/A') AS Chkin
from checkinout b
where month(b.checktime) = 6
AND year(b.checktime) = 2019
AND weekday(b.checktime) not in (5, 6) -- non weekend
AND date(b.checktime) not in (select date_s from wend)
ORDER BY dtDate DESC
Though GROUP BY might perform better than DISTINCT - You should test both. However, the above query can be optimized to use indexes.
The outer condition month(b.checktime) = 6 AND year(b.checktime) = 2019 can be rewritten to b.checktime >= '2019-06-01' AND b.checktime < '2019-06-01' + INTERVAL 1 MONTH. This way the engine should be able to use an index on (checktime).
The condition date(a.checktime) = date(b.checktime) can be written as a.checktime >= date(b.checktime) and a.checktime < date(b.checktime) + INTERVAL 1 DAY. Here I suggest one of the following indexes: (checktype, userid, checktime), (userid, checktype, checktime) or (userid, checktime).
And for date(b.checktime) not in (select date_s from wend) it might be better to use an "anti-join".
So here is the final query, which I would try:
SELECT DISTINCT date(b.checktime) AS dtDate,
coalesce((
SELECT time(a.checktime)
FROM checkinout a
WHERE a.checktype = '0'
and a.userid = 1
and a.checktime >= date(b.checktime)
and a.checktime < date(b.checktime) + INTERVAL 1 DAY
LIMIT 1
), 'N/A') AS Chkin
from checkinout b
LEFT JOIN wend w ON w.date_s = date(b.checktime)
where b.checktime >= '2019-06-01'
AND b.checktime < '2019-06-01' + INTERVAL 1 MONTH
AND weekday(b.checktime) not in (5, 6) -- non weekend
AND w.date_s IS NULL
ORDER BY dtDate DESC

How to do SUM(MAX( ) + MAX( ))?

Is there a proper way to do SUM(MAX() + MAX())?
Here's what I've been trying to do
SELECT
SUM(MAX(account.BALANCE1) + MAX(account.BALANCE2)) AS TOTALBALANCE
FROM
account
JOIN
transaction t ON account.PRIMARYKEY = t.ACCOUNTKEY
WHERE
NOT EXISTS( SELECT
1
FROM
transaction a
WHERE
a.ACCOUNTKEY = t.ACCOUNTKEY
AND a.TYPE = 'PAYMENT')
HAVING TOTALBALANCE > 0
It reads:
Error Code: 1111. Invalid use of group function
Since you don't have any GROUP BY clause specified,
MAX(account.BALANCE1) + MAX(account.BALANCE2)
should aready suffice your needs.

getting error from mysqli_fetch_array

My query line is:
SELECT TR.*,
PL.*, DE.*,
( DE.power + DE.stamina + DE.violence + DE.speed + DE.shooting + DE.scoring + DE.pass + DE.ball_control + DE.talent ) AS TPOWER,
strftime('%Y-%d-%m', DE.age, 'unixepoch') AS age
FROM `transfers` TR JOIN `players` PL ON TR.player_id=PL.id
JOIN `playerdetails` DE ON TR.player_id=DE.player_id
WHERE PL.position = 'MD' AND ( age >= '20' AND age <= '24' )
AND PL.firstname = 'a' AND PL.lastname = 'b' AND TPOWER >= '1'
AND TPOWER <= '5' AND TR.price >= '20' AND TR.price <= '50'
ORDER BY age DESC
What's wrong with this query?
An error occurred:
Warning: mysqli_fetch_array() expects parameter 1 to be mysqli_result, boolean given in E:\EasyPHP-Devserver-16.1\eds-www\classes\DB.php on line 15
MySQL doesn't have a function called strftime(). You might want date_format() instead:
SELECT . . .
date_format(de.age, '%Y-%d-%m') AS age
However, that seems like a strange way to express the age (which is usually an integer, number, or interval).
Your query could have other errors as well. You should check the error messages that are returned.

MySQL Function, must bring back a row

I have this simple MySQL statement:
SELECT
((AVG(q1) + AVG(q8) + AVG(q15)) / 3 ) AS Res
FROM tresults
WHERE id = '1' AND date = 'MARCH2010' AND q25 = '1'
GROUP BY q25
Now, if there are no rows with the date MARCH2010 then the query returns zero results (which is correct) but I'd like it to return a row - even if the result is NULL.
You can just select a single row as a constant, and then left join it to your result set:
select l.*, r.*
from (select "your constant" as constant) as l
left join (
SELECT
((AVG(q1) + AVG(q8) + AVG(q15)) / 3 ) AS Res
FROM tresults
WHERE id = '1' AND date = 'MARCH2010' AND q25 = '1'
GROUP BY q25
) as r on 1
How this works:
select "your constant" as constant always returns a single row
left join always returns all of the rows in the left table at least once
if the right table has no rows, then the entire left table is extended with a bunch of null columns, and the result has one row
if the right table has n rows, the result has n rows that each have an additional "your constant" column
I'm not absolutely positive, but this case statement might work. I can't test it atm.
Case When
(SELECT
Count(*)
FROM tresults
WHERE id = '1' AND date = 'MARCH2010' AND q25 = '1'
GROUP BY q25) > 0
Then
SELECT
((AVG(q1) + AVG(q8) + AVG(q15)) / 3 ) AS Res
FROM tresults
WHERE id = '1' AND date = 'MARCH2010' AND q25 = '1'
GROUP BY q25
Else
SELECT null
End
SELECT
((AVG(q1) + AVG(q8) + AVG(q15)) / 3 ) AS Res
FROM tresults
WHERE id = '1' AND date = 'MARCH2010' AND q25 = '1'
GROUP BY q25
UNION ALL
SELECT NULL AS Res
FROM dual
WHERE NOT EXISTS (
SELECT
((AVG(q1) + AVG(q8) + AVG(q15)) / 3 ) AS Res
FROM tresults
WHERE id = '1' AND date = 'MARCH2010' AND q25 = '1'
GROUP BY q25
)
Will always return one row beacuse of second part.

trying to get the single exp payment

I have a query like this
SELECT member_Id ,
PERIOD_DIFF(
DATE_FORMAT(now(),'%Y%m'),
DATE_FORMAT(memberToMship_StartDate,'%Y%m')
) +
(
DAY(memberToMship_StartDate) < memberToMship_DueDay
) +
(
DAY(now()) > memberToMship_DueDay
) - 1
AS ExpPayments
FROM membertomships
it was giving all exp payments for all members that was fine, can i get the single exp payment for single member.....
Do i need add any join or any where condition ..
If you know the member_Id you could just add a WHERE clause :
SELECT member_Id ,
PERIOD_DIFF(
DATE_FORMAT(now(),'%Y%m'),
DATE_FORMAT(memberToMship_StartDate,'%Y%m')
) +
(
DAY(memberToMship_StartDate) < memberToMship_DueDay
) +
(
DAY(now()) > memberToMship_DueDay
) - 1
AS ExpPayments
FROM membertomships
WHERE member_Id = 213
add where clause in the end of the query
where member_Id = {enter the id}