Unknown column in subquery - mysql - mysql

I am very close to completing this difficult query. It's quite long, so hopefully not too overwhelming. But in my case statment in the select block I am referencing a union from my where statement. It is giving me "MySQL Database Error: Unknown column 'U.EmpID' in 'where clause'". Any help would be much appreciated. And here is the query:
SELECT U.EmpID,
CASE
WHEN ((SELECT COUNT(*)
FROM (SELECT *
FROM timeclock_copy tp
WHERE PunchEvent = 'breakin'
AND DATE(tp.PunchDateTime) =
'2013-11-12'
AND tp.EmpID = U.EmpID) AS s) > 1)
AND ((SELECT COUNT(*)
FROM (SELECT *
FROM timeclock_copy tp
WHERE PunchEvent = 'breakout'
AND DATE(tp.PunchDateTime) =
'2013-11-12'
AND tp.EmpID = U.EmpID) AS s) > 1)
THEN
"MULTIPLE BREAKS"
ELSE
"ONE BREAK"
END
AS Lunch
FROM ((SELECT `enter`.EmpID,
`enter`.PunchDateTime AS `time`,
DATE_FORMAT(`enter`.PunchDateTime, '%m-%d-%Y')
AS 'Punch Date',
TIMESTAMPDIFF(SECOND,
`enter`.PunchDateTime,
'2003-05-01 00:00:00')
AS `delta`
FROM timeclock_copy AS `enter`
WHERE `enter`.`In-Out` = 1)
UNION
(SELECT `leave`.EmpID,
`leave`.PunchDateTime AS `time`,
DATE_FORMAT(`leave`.PunchDateTime, '%m-%d-%Y')
AS 'Punch Date',
-TIMESTAMPDIFF(SECOND,
`leave`.PunchDateTime,
'2003-05-01 00:00:00')
AS `delta`
FROM timeclock_copy AS `leave`
WHERE `leave`.`In-Out` = 0)) AS U
LEFT JOIN testclb.prempl pe ON u.EmpID = pe.prempl
WHERE DATE(U.`time`) >= '2013-11-12' AND DATE(U.`time`) < '2013-11-13'
GROUP BY date(U.`time`), EmpID
ORDER BY U.EmpID, U.`time` ASC

Subqueries in FROM clauses cannot be correlated with the outer statement. I think this is why you are getting the Unknown column 'U.EmpID' in 'where clause'" error.

Related

Convert mysql to doctrine

I have the following MySQL query
select a.*, d.*, p.*, pow.* from appointment a
left join doctor d on d.id = a.doctor_id
left join patient p on p.id = a.patient_id
left join point_of_work pow on pow.id = a.point_of_work_id
where (doctor_id, patient_id, date) = (
select doctor_id, patient_id,
coalesce(
min(case when date > curdate() then date end),
max(case when date < curdate() then date end)
) date
from appointment
where (doctor_id, patient_id) = (a.doctor_id, a.patient_id)
)
and d.external_id = 1
And I am trying to convert it to DQL.
Right now I come to this version of DQL but it seems I'am doing something (or maybe more things:( wrong)
$expr = $this->getEntityManager()->getExpressionBuilder();
$queryBuilder = $this->createQueryBuilder('a')
->leftJoin(Doctor::class, 'd')
->leftJoin(Patient::class, 'p')
->leftJoin(PointOfWork::class, 'pow')
->where(
$expr->eq('doctorId, patient_id, date',
$this->createQueryBuilder('a')
->select(Appointment::class . ',
coalesce(
min(case when date > curdate() then date end),
max(case when date < curdate() then date end)
) date'
)
->where ('(doctorId, patientId) = (a.doctorId, a.patientId)')
)
)
->andWhere('d.externalId = :externalId')
->setParameter('externalId', $doctorExternalId)
->setMaxResults($limit)
->setFirstResult($offset);
What approaches do I need for the DQL conversion?

mysql error: FUNCTION asterisk.SUM does not exist. (Apache superset)

I connected the mysql database and ran a direct sql query and I got the correct table, I wanted to visualize it and clicked the "Explore" button, but I got the error: "mysql error: FUNCTION asterisk.SUM does not exist. Check the ' Function Name Parsing and Resolution 'section in the Reference Manual "Please tell me where I made a mistake, thanks.
working sql request
error
My sql request:
SELECT DATE_FORMAT(start, '%Y-%m-%d') AS Date,
disposition AS Type,
DATE_FORMAT(SEC_TO_TIME(SUM(end-start)),'%H:%i:%S') AS Call_duration,
case
when substring(dstchannel,5,4) = '1000' then 'Name1'
when substring(dstchannel,5,4) = '2000' then 'Name2'
when substring(dstchannel,5,4) = '3000' then 'Name3'
when substring(dstchannel,5,4) = '4000' then 'Name4'
when substring(dstchannel,5,3) = '100' then 'Other'
end AS Operator,
count(*) AS Number_of_calls
FROM cdr
WHERE dcontext = 'call-in'
AND disposition = 'ANSWERED'
AND end-start > 0
group by DATE_FORMAT(start, '%Y-%m-%d'), 4
order by 1 desc
My request works correctly, but when I try to create a chart, superset changes the request and it has a line break after SUM. Сan I fix this without changing the database configuration?
Superset out query:
SELECT `Date` AS `Date`,
`Type` AS `Type`,
`Call_duration` AS `Call_duration`,
`Operator` AS `Operator`,
`Number_of_calls` AS `Number_of_calls`
FROM
(SELECT DATE_FORMAT
(start, '%Y-%m-%d') AS Date,
disposition AS Type,
DATE_FORMAT(SEC_TO_TIME(SUM
(end-start)), '%H:%i:%S') AS Call_duration,
case
when substring(dstchannel, 5, 4) = '1000' then 'Name1'
when substring(dstchannel, 5, 4) = '2000' then 'Name2'
when substring(dstchannel, 5, 4) = '3000' then 'Name3'
when substring(dstchannel, 5, 4) = '4000' then 'Name4'
when substring(dstchannel, 5, 3) = '100' then 'Other'
end AS
Operator,
count(*) AS Number_of_calls
FROM cdr
WHERE dcontext = 'call-in'
AND disposition = 'ANSWERED'
AND end-
start > 0
group by DATE_FORMAT
(start, '%Y-%m-%d'),
4
order by 1 desc) AS expr_qry
LIMIT 1000;
Your group by doesn't match the select columns. Try:
SELECT DATE_FORMAT(start, '%Y-%m-%d') AS Date,
disposition AS Type,
DATE_FORMAT(SEC_TO_TIME(SUM(end-start)), '%H:%i:%S') AS Call_duration,
(case when substring(dstchannel,5,4) = '1000' then 'Name1'
when substring(dstchannel,5,4) = '2000' then 'Name2'
when substring(dstchannel,5,4) = '3000' then 'Name3'
when substring(dstchannel,5,4) = '4000' then 'Name4'
when substring(dstchannel,5,3) = '100' then 'Other'
end) AS Operator,
count(*) AS Number_of_calls
FROM cdr
WHERE dcontext = 'call-in' AND
disposition = 'ANSWERED'
end > start
group by DATE_FORMAT(start, '%Y-%m-%d'), type, call_duration, operator
order by 1 desc

SQL Query - adding max condition for distinct name

Warmest thanks by advance for your help
My current SQL query :
SELECT
`id`,
`comp`,
`jour`,
`hippo`,
`numcourse`,
`cl`,
`dist`,
`partant`,
`typec`,
`cheque`,
`numero`,
`cheval`,
`age`,
`cotedirect`
FROM `turf_12dec`.`cachedate` c
WHERE
`partant` > '7'
AND `typec` = 'Attelé'
AND `jour` > '2017-01-01'
AND `cl` != ''
AND `cl`!= 'NP'
That I wish :
AND max(jour) for distinct cheval is > '2019-01-01'
This query:
SELECT `cheval`
FROM `turf_12dec`.`cachedate`
GROUP BY `cheval`
HAVING MAX(`jour`) > '2019-01-01'
returns all the chevals that you describe in your condition and you can join it to the table:
SELECT t.`id`, t.`comp`, t.`jour`, t.`hippo`, t.`numcourse`, t.`cl`,
t.`dist`, t.`partant`, t.`typec`, t.`cheque`, t.`numero`,
t.`cheval`, t.`age`, t.`cotedirect`
FROM `turf_12dec`.`cachedate` t INNER JOIN (
SELECT `cheval`
FROM `turf_12dec`.`cachedate`
GROUP BY `cheval`
HAVING MAX(`jour`) > '2019-01-01'
) tt ON tt.`cheval` = t.`cheval`
WHERE t.`partant` > '7' and
t.`typec` = 'Attelé' and
t.`jour` > '2017-01-01' and
t.`cl` != '' AND
t.`cl`!= 'NP'
You can add a correlated subquery:
and exists (select 1
from `turf_12dec`.`cachedate` cd
where cd.cheval = cachedate.cheval and cd.jour > '2019-01-01'
)
You don't mention the additional filtering conditions. You may need to repeat them in the subquery as well, if they should also apply to the maximum jour.
You could add an additional filter with a correlated subquery:
SELECT
`id`,
`comp`,
`jour`,
`hippo`,
`numcourse`,
`cl`,
`dist`,
`partant`,
`typec`,
`cheque`,
`numero`,
`cheval`,
`age`,
`cotedirect`
FROM `turf_12dec`.`cachedate` c
WHERE
`partant` > '7'
AND `typec` = 'Attelé'
AND `jour` > '2017-01-01'
AND `cl` != ''
AND `cl`!= 'NP'
AND (
SELECT MAX(`jour`)
FROM `turf_12dec`.`cachedate` c1
WHERE c1.`cheval` = c.`cheval`
) > '2019-01-01'
This can also be expressed with an EXITS condition:
AND EXISTS (
SELECT 1
FROM `turf_12dec`.`cachedate`
WHERE c1.`cheval` = c.`cheval` AND `jour` > '2019-01-01'
)

Query using group by month

I have problem with the query using group by month. This query returns total_revenue per month. but if month of year doesn't contain any data then total_revnue is increased unnecessarily.
SELECT COUNT(CT.cumTxnReportId),
CT.cumTxnReportId,
CT.ticketNum,
DATE_FORMAT(CT.exitDateTimeUtc,'%m-%Y'),
sum(netAmount) AS total_revenue,
D.name,
HOUR(CT.entranceDateTimeUtc) AS entryHour,
HOUR(CT.exitDateTimeUtc) AS exitHour,
CT.entranceDateTimeUtc,
CT.exitDateTimeUtc,
CT.netAmount AS netAmount,
CT.grossAmount,
CT.discountAmount,
CT.rate,
CT.txnType,
CT.ticketType,
CT.txnNum,
CT.numDiscounts
FROM Parkloco.ParkingArea PA
JOIN IParcPro.Device D ON PA.id = D.parkingAreaId
JOIN Parkloco.RateCard RC ON PA.id = RC.parkingAreaId
JOIN IParcPro.CumTxn CT ON D.id = CT.deviceId
WHERE PA.uuid = '27d842c1-7057-11e6-a0eb-1245b0d35d23'
AND (CT.txnType = 'Allowed'
OR CT.txnType = 'Add'
OR CT.txnType = 'Normal'
OR CT.txnType = 'Offline'
OR CT.txnType = 'Repay')
AND ((CT.entranceDateTimeUtc >= '2016-08-01 00:00:00'
AND CT.exitDateTimeUtc <= '2017-04-31 23:59:59'))
AND (RC.state = 'active'
OR RC.state = 'archived')
AND RC.fromDateTimeUtc <= '2017-04-31 23:59:59'
AND (RC.thruDateTimeUtc IS NULL
OR RC.thruDateTimeUtc >= '2016-08-01 00:00:00')
AND (TIMESTAMPDIFF (SECOND, CT.entranceDateTimeUtc, CT.exitDateTimeUtc) >= '0' * 60)
AND (TIMESTAMPDIFF (SECOND, CT.entranceDateTimeUtc, CT.exitDateTimeUtc) < '1441' * 60)
AND CT.numDiscounts=0
AND CT.ticketNum !=0
GROUP BY DATE_FORMAT(CT.exitDateTimeUtc,'%m-%Y')
but when I am increasing the range month - at that point of time I am getting unneccessary increment in total_revenue
SELECT COUNT(CT.cumTxnReportId),
CT.cumTxnReportId,
CT.ticketNum,
DATE_FORMAT(CT.exitDateTimeUtc,'%m-%Y'),
sum(netAmount) AS total_revenue,
D.name,
HOUR(CT.entranceDateTimeUtc) AS entryHour,
HOUR(CT.exitDateTimeUtc) AS exitHour,
CT.entranceDateTimeUtc,
CT.exitDateTimeUtc,
CT.netAmount AS netAmount,
CT.grossAmount,
CT.discountAmount,
CT.rate,
CT.txnType,
CT.ticketType,
CT.txnNum,
CT.numDiscounts
FROM Parkloco.ParkingArea PA
JOIN IParcPro.Device D ON PA.id = D.parkingAreaId
JOIN Parkloco.RateCard RC ON PA.id = RC.parkingAreaId
JOIN IParcPro.CumTxn CT ON D.id = CT.deviceId
WHERE PA.uuid = '27d842c1-7057-11e6-a0eb-1245b0d35d23'
AND (CT.txnType = 'Allowed'
OR CT.txnType = 'Add'
OR CT.txnType = 'Normal'
OR CT.txnType = 'Offline'
OR CT.txnType = 'Repay')
AND ((CT.entranceDateTimeUtc >= '2016-08-01 00:00:00'
AND CT.exitDateTimeUtc <= '2017-07-31 23:59:59'))
AND (RC.state = 'active'
OR RC.state = 'archived')
AND RC.fromDateTimeUtc <= '2017-07-31 23:59:59'
AND (RC.thruDateTimeUtc IS NULL
OR RC.thruDateTimeUtc >= '2016-08-01 00:00:00')
AND (TIMESTAMPDIFF (SECOND, CT.entranceDateTimeUtc, CT.exitDateTimeUtc) >= '0' * 60)
AND (TIMESTAMPDIFF (SECOND, CT.entranceDateTimeUtc, CT.exitDateTimeUtc) < '1441' * 60)
AND CT.numDiscounts=0
AND CT.ticketNum !=0
GROUP BY DATE_FORMAT(CT.exitDateTimeUtc,'%m-%Y')
output such as :
can anyone help me on this? Thanks in advance if you could let me know.
Despite MySQL allow this weird group by rules, in my opinion, you should to avoid use it. I explain, usually, all select clause non aggregate fields should appear on group by clause:
select a,b,c, sum(z)
from t
group by a,b,c
vs
select a,b,c, sum(z)
from t
group by a #<--- MySQL allow this!
Then, if b and c are not in group by, how MySQL figure up the right fields to be selected? Like this on <5.6:
The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate.
In my opinion, in your query has no sense: Look entryHour and total_revenue. One is for an entry the other one is for all month.
I guess you should to rethink the hole sql statement. Because the result of this one is incoherent.
Also, remember this is not 'code revision service'. Please, read how to create a Minimal, Complete, and Verifiable example in order your question also help other users.

How to add another column returned for complicated MySQL query

I have a rather complicated MySQL query that looks like this:
SELECT CONCAT(pe.first, ' ', pe.last) AS Name,
tp.EmpID as 'Empl ID',
DATE_FORMAT(tp.PunchDateTime, '%m-%d-%Y') AS 'Punch Date',
DATE_FORMAT(tp.PunchDateTime, '%W') AS 'Weekday',
TRUNCATE((SUM(UNIX_TIMESTAMP(PunchDateTime) * (1 - 2 * `In-Out`)) / 3600),2)
AS 'Hours Worked'
FROM timeclock_punchlog tp LEFT JOIN prempl01 pe ON tp.EmpID = pe.prempl
WHERE tp.PunchDateTime >= '2013-06-16' and tp.PunchDateTime < '2013-06-23'
AND tp.EmpID = 1588
GROUP BY date(PunchDateTime), EmpID
ORDER BY Name, `Punch Date` ASC
Now I need to add a 6th column. I need to know how long the employee's lunch was. I think it's going to involve a subquery in the select section, because it would be too complicated to get it any other way. Calculating the 'Hours Worked' was complicated because I needed to calculate the (breakout - clockin) + (clockout - breakin) for each day. Now I need to calculate breakin - breakout for each of those days as well. Here is the structure for the current table for one employee for one day.
PunchID EmpID PunchEvent PunchDateTime In-Out
308 1588 clockin 6/17/2013 6:20:48 AM Checked
313 1588 breakout 6/17/2013 12:15:18 PM Unchecked
315 1588 breakin 6/17/2013 12:43:58 PM Checked
319 1588 clockout 6/17/2013 5:00:37 PM Unchecked
I can't figure out how I would add the lunch break time to the above query. Hopefully I have provided all the information needed.
Update: I have put together a working query that does what I want for a specific day and specific employee. Now what I need is for this query to work for all employees for a specific date range(ie week). Here is the query:
SELECT CONCAT(pe.first, ' ', pe.last) AS Name,
tp.EmpID AS 'Empl ID',
DATE_FORMAT(tp.PunchDateTime, '%m-%d-%Y') AS 'Punch Date',
DATE_FORMAT(tp.PunchDateTime, '%W') AS 'Weekday',
TRUNCATE((SUM(UNIX_TIMESTAMP(PunchDateTime) * (1 - 2 * `In-Out`)) / 3600), 2)
AS 'Hours Worked',
(SELECT TIMEDIFF
((SELECT DATE_FORMAT(tpl.PunchDateTime, '%r') as dTime FROM timeclock_punchlog tpl WHERE tpl.PunchEvent = 'breakin' AND tpl.EmpID = 1588 AND DATE(tpl.PunchDateTime) = '2013-06-17'),
(SELECT DATE_FORMAT(tpl.PunchDateTime, '%r') as dTime FROM timeclock_punchlog tpl WHERE tpl.PunchEvent = 'breakout' AND tpl.EmpID = 1588 AND DATE(tpl.PunchDateTime) = '2013-06-17'))) as 'Lunch'
FROM timeclock_punchlog tp LEFT JOIN prempl01 pe ON tp.EmpID = pe.prempl
WHERE DATE(tp.PunchDateTime) = '2013-06-17'
AND tp.EmpID = 1588
GROUP BY date(PunchDateTime), EmpID
ORDER BY Name, `Punch Date` ASC
And the result:
Name Empl ID Punch Date Weekday Hours Worked Lunch
BRUCE COLEMAN 1588 06-17-2013 Monday 10.18 00:28:40
Now if someone can figure out how to make that query work without specifying the employee ID and without specifying an exact date, make it a date range instead.
You should replace both tpl.EmpID = 1588 with tpl.EmpID = tp.EmpID and remove the AND tp.EmpID = 1588.
Edit:
SELECT CONCAT(pe.first, ' ', pe.last) AS Name,
tp.EmpID AS 'Empl ID',
DATE_FORMAT(tp.PunchDateTime, '%m-%d-%Y') AS 'Punch Date',
DATE_FORMAT(tp.PunchDateTime, '%W') AS 'Weekday',
TRUNCATE((SUM(UNIX_TIMESTAMP(PunchDateTime) * (1 - 2 * `In-Out`)) / 3600), 2) AS 'Hours Worked',
(SELECT TIMEDIFF((SELECT DATE_FORMAT(tpl.PunchDateTime, '%r') as dTime FROM timeclock_punchlog tpl WHERE tpl.PunchEvent = 'breakin' AND tpl.EmpID = tp.EmpID AND DATE(tpl.PunchDateTime) = '2013-06-17'),
(SELECT DATE_FORMAT(tpl.PunchDateTime, '%r') as dTime FROM timeclock_punchlog tpl WHERE tpl.PunchEvent = 'breakout' AND tpl.EmpID = tp.EmpID AND DATE(tpl.PunchDateTime) = '2013-06-17'))) as 'Lunch'
FROM timeclock_punchlog tp LEFT JOIN prempl01 pe ON tp.EmpID = pe.prempl
WHERE DATE(tp.PunchDateTime) = '2013-06-17'
GROUP BY date(PunchDateTime), EmpID
ORDER BY Name, `Punch Date` ASC