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.
Related
I'm writing some SQL queries, and an error occurred:
psycopg2.errors.SyntaxError: syntax error at or near "1"
LINE 10: ... AND A2.block_time < DATE_ADD(A1.block_time, INTERVAL 1 DAY)
My query where the error occurred is:
SELECT address_id
FROM address_history A1
WHERE EXISTS (
SELECT *
FROM address_history A2
WHERE A1.address_id = A2.address_id
AND A1.inflow = A2.outflow
AND A2.block_time > A1.block_time
AND A2.block_time < DATE_ADD(A1.block_time, INTERVAL 1 DAY)
AND A1.address_id IN ( ... ) # some candidates
)
and data in the block_time column are of the form:
2020-01-03 14:10:00
so I don't think I need to cast data with CAST() or DATE(). What's wrong with this SQL query?
Part of my Python code
mySQL_user = '''
SELECT address_id
FROM address_history A1
WHERE EXISTS (
SELECT *
FROM address_history A2
WHERE A1.address_id = A2.address_id
AND A1.inflow = A2.outflow
AND A2.block_time > A1.block_time
AND A2.block_time < DATE_ADD(A1.block_time, INTERVAL 1 DAY)
AND A1.address_id IN (
'''
Above code is the skeleton of my query, and I appended some candidates using:
mySQL_user += f"'{address}'"
where address is a string variable. I also separated candidates using ", "(comma), and I added two ")" at the end using:
mySQL_user += "))"
how can i add an "order by created_on asc" in this request :
(select user.first_name as prenom, user.last_name as nom, fvll.created_on, fvll.bar_code, "R" from stk_fuel_voucher_line fvll,stk_fuel_voucher fv, adm_user user
where YEAR(fvll.created_on)=? and MONTH(fvll.created_on) = ? and user.id=fv.id_user and fv.id=fvll.id_fuel_voucher and
fvll.bar_code not in
(select fvl.bar_code
from stk_fuel_voucher_line fvl, stk_fuel_voucher_book fvb
where fvl.bar_code >= fvb.first_bar_code and fvl.bar_code <=fvb.last_bar_code
and YEAR(fvl.created_on)=? and MONTH(fvl.created_on) = ?))
UNION
(select user2.first_name as prenom, user2.last_name as nom, fvll2.created_on, fvll2.bar_code, "B"
from stk_fuel_voucher fv2, stk_fuel_voucher_book fvb2, stk_fuel_voucher_line fvll2, adm_user user2
where fvll2.bar_code >= fvb2.first_bar_code and fvll2.bar_code <=fvb2.last_bar_code and user2.id=fv2.id_user and fv2.id=fvll2.id_fuel_voucher
and YEAR(fvll2.created_on)=? and MONTH(fvll2.created_on) = ?)
It looks to me like the two queries are the same, with the only difference being detecting whether there's a matching bar_code, and returning 'B' or 'R' depending.
I'd avoid the redundant rigmarole of the UNION and just do one query, with a conditional test to determine whether a 'B' or 'R' is returned.
If the intent of the UNION operator (in place of the more usual UNION ALL) is to remove duplicates from each set, we can use a GROUP BY clause or DISTINCT keyword to achieve that. (In the original query, we are guaranteed that there won't be duplicates between the two sets, on set always as an 'R', the other set always has a 'B'.
I don't have an understanding of the specification for the query, but based on what I am able to discern from the existing query, I would tend to do something like this instead:
SELECT user.first_name AS prenom
, user.last_name AS nom
, fvll.created_on AS created_on
, fvll.bar_code
, CASE WHEN ni.bar_code IS NULL THEN 'R' ELSE 'B' END AS r
FROM stk_fuel_voucher_line fvll
JOIN stk_fuel_voucher fv
ON fv.id = fvll.id_fuel_voucher
JOIN adm_user user
ON user.id = fv.id_user
LEFT
JOIN ( SELECT fvl.bar_code
FROM stk_fuel_voucher_line fvl
JOIN stk_fuel_voucher_book fvb
ON fvb.first_bar_code <= fvl.bar_code
AND fvb.last_bar_code >= fvl.bar_code
WHERE YEAR(fvl.created_on) = ?
AND MONTH(fvl.created_on) = ?
GROUP BY fvl.bar_code
) ni
ON ni.bar_code = fvll.bar_code
WHERE YEAR(fvll.created_on) = ?
AND MONTH(fvll.created_on) = ?
GROUP
BY user.first_name AS prenom
, user.last_name AS nom
, fvll.created_on
, fvll.bar_code
, CASE WHEN ni.bar_code IS NULL THEN 'R' ELSE 'B' END
ORDER
BY fv11.created_on
Again, if we aren't concerned with removing duplicates, then we could remove the GROUP BY clause.
For the date comparisons, I'd opt for comparing the raw dates, so the query could make effective use of an index range scan operation.
Rather than this:
WHERE YEAR(fvll.created_on) = ?
AND MONTH(fvll.created_on) = ?
I would write something like
WHERE fvll.created_on >= month_begin_dt + INTERVAL 0 MONTH
AND fvll.created_on >= month_begin_dt + INTERVAL 1 MONTH
with month_begin_dt representing an expression that returns the first day of the month, however that needs to get passed in, if we need to construct a DATE from a year and a month, we could do that. The end goal would be to have equivalent to:
WHERE fvll.created_on >= '2018-05-01' + INTERVAL 0 MONTH
AND fvll.created_on >= '2018-05-01' + INTERVAL 1 MONTH
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.
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 ...
)
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.