I'm try to use the result of a subquery in the query's WHERE clause. The attribute I am wishing to use is last_contact. See below.
SELECT forename, surname, type,
( SELECT MAX(completed_date)
FROM tblTasks
WHERE prospect_id = tblProspects.prospect_id AND completed = '1'
) AS last_contact,
created_at
FROM tblProspects
WHERE hidden != '1' AND type='Prospect' AND last_contact > DATE_ADD(CURDATE(), INTERVAL -90 DAY)
ORDER BY last_contact ASC
I get the SQL Error: #1054 - Unknown column 'last_contact' in 'where clause'
Any help would be greatly appreciated.
Thanks.
You need to use HAVING clause in order to refine your results by custom aliased coulmn they cannot be used in where clause
SELECT
forename,
surname,
type,
(SELECT MAX(completed_date) FROM tblTasks WHERE prospect_id = tblProspects.prospect_id AND completed = '1') AS last_contact,
created_at
FROM tblProspects
WHERE hidden != '1' AND type='Prospect'
HAVING (
last_contact > DATE_ADD(CURDATE(), INTERVAL -90 DAY)
OR last_contact IS NULL
)
ORDER BY last_contact ASC
Related
Since my web-host has updated the MySQL server version, my old SQL Query is not working anymore:
select COUNT(ID) AS Anzahl,
DAY(STR_TO_DATE(created_at, '%Y-%m-%d')) AS Datum
from `leads`
where `created_at` >= 2018-02-01
and `created_at` <= 2018-02-15
and `shopID` = 20
group by DAY(created_at)
order by DAY(created_at) asc
That means, I have to create a full group by query. I already have read this article but I don't really get it.
I should name all columns which are unique
Thats what I don't get. If I want to count the ID, I cannot create a group by ID query because in this case my count would always be 1. Could anybody please explain to me how full group by works and how my statement would like with a full group by statement?
Just use the same expression in the select as in the group by:
select COUNT(ID) AS Anzahl, DAY(created_at) AS Datum
from `leads` l
where `created_at` >= '2018-02-01' and
`created_at` <= '2018-02-15' and
`shopID` = 20
group by DAY(created_at)
order by DAY(created_at) asc;
You also need single quotes around the date constants.
Your select and group by columns doesn't match. You should make them same. Try below query:
select COUNT(ID) AS Anzahl,
DAY(STR_TO_DATE(created_at, '%Y-%m-%d')) AS Datum
from `leads`
where `created_at` >= 2018-02-01
and `created_at` <= 2018-02-15
and `shopID` = 20
group by Datum
order by Datum asc
Here is my query:
SELECT SUM(score) score,
type,
context,
post_id,
e.table_code,
comment_id,
MIN(seen) seen,
MAX(date_time) d_t,
(CASE WHEN FROM_UNIXTIME(MAX(date_time)) >= CURDATE() THEN 'today'
WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday'
WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week'
ELSE 'in last month'
END) as range_day
FROM `events` e
WHERE e.id IN ($ids)
GROUP BY type, post_id, e.table_code, comment_id, range_day
ORDER BY seen, MAX(date_time) desc, MAX(e.id) desc
It throws this error:
#1056 - Can't group on 'range_day'
And if I remove range_day from GROUP BY clause, then it works as well. But I need to also group the result also based on range_day. How can I do that?
Not sure what you are trying to do. But you can wrap your query into a subquery without range_day in the GROUP BY clause. Then use your GROUP BY clause in the outer query as it is.
SELECT SUM(score) score,
type,
context, -- WARNING! Not listed in group by clause
post_id,
table_code,
comment_id,
MIN(seen) seen,
MAX(d_t) d_t,
range_day
FROM (
SELECT SUM(score) score,
MAX(id) as id,
type,
context, -- WARNING! Not listed in group by clause
post_id,
e.table_code,
comment_id,
MIN(seen) seen,
MAX(date_time) d_t,
(CASE WHEN FROM_UNIXTIME(MAX(date_time)) >= CURDATE() THEN 'today'
WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday'
WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week'
ELSE 'in last month'
END) as range_day
FROM `events` e
WHERE e.id IN ($ids)
GROUP BY type, post_id, e.table_code, comment_id
) sub
GROUP BY type, post_id, table_code, comment_id, range_day
ORDER BY seen, MAX(d_t) desc, MAX(id) desc
However - you select context without aggregation wich is not listed in the GROUP BY clause. Thus you will get some "random" value from the group. In strict mode the query will fail.
Your definition of range_day doesn't exactly make sense. Why does it use MAX()? Max of what?
A natural way to make the query work is to remove the MAX() from the definition:
SELECT SUM(score) score, type, context, post_id, e.table_code, comment_id,
MIN(seen) as seen, MAX(date_time) as d_t,
(CASE WHEN FROM_UNIXTIME(date_time) >= CURDATE() THEN 'today'
WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday'
WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week'
ELSE 'in last month'
END) as range_day
FROM `events` e
WHERE e.id IN ($ids)
GROUP BY type, post_id, e.table_code, comment_id, range_day
ORDER BY seen, MAX(date_time) desc, MAX(e.id) desc;
More comments:
The IN ($ids) probably doesn't do what you expect. The variables $ids is treated as a single value, so this is equivalent to e.di = $ids.
If this doesn't do what you want, then you might want MAX() at some other level of aggregation. That would require an additional subquery.
First, your problem...
You cannot GROUP BY an aggregate. Notice the MAX() inside range_day. Your GROUP BY should include all non-aggregate items in the SELECT. context is missing and may lead to an error in subsequent releases.
Then another problem...
MIN(seen) seen,
MAX(d_t) d_t,
...
ORDER BY seen,
MAX(d_t) desc
Notice an inconsistency? An ambiguity? Is seen (in the ORDER BY) supposed to be the original seen, or the alias seen, meaning MIN(seen)? Ditto for d_t?
Always try to avoid having an alias spelled the same as a column name when you need to refer to it later. In WHERE, it must be the column name; in ORDER BY and HAVING, it is the alias.
So, I think, this is wrong: MAX(d_t) desc in the ORDER BY.
When I run this query I have this error message on phpmydamin: Unknown column 'timestamp' in 'having clause'
My column name is timestamp
SELECT DISTINCT (
hash
) AS total
FROM behaviour
HAVING total =1 and date(timestamp) = curdate()
How to get the number of hash for today?
Use where. And parentheses are not appropriate for select distinct (distinct is not a function). I suspect that you intend:
SELECT COUNT(DISTINCT hash) AS total
FROM behaviour
WHERE date(timestamp) = curdate();
It is better to write the WHERE clause without using a function on the column:
SELECT COUNT(DISTINCT hash) AS total
FROM behaviour
WHERE timestamp >= curdate() AND timestamp < date_add(curdate, interval 1 day);
Although more complicated, it allows the database engine to use an index on behaviour(timestamp) (or better yet, on behaviour(timestamp, hash).
EDIT:
If you want the hash that only appear once, one method is a subquery:
select count(*)
from (select hash
from behaviour
where timestamp >= curdate() AND timestamp < date_add(curdate, interval 1 day)
group by hash
having count(*) = 1
);
To count the hash values only existing once:
select count(*)
from
(
select hash
from behavior
where date(timestamp) = curdate()
group by hash
having count(*) = 1
) dt
The inner select (derived table) will return the hash values only existing once. The outer select will count those rows.
I'm really blocked at an advanced query, if someone can help me
I have a table mysql that looks like:
customers(id, appointment_date1, appointment_date2, appointment_date3, appointment_date4)
I'm looking for a query that list me what is the next most recent appointment
Before I do this query :
SELECT CASE
WHEN (customers.appointment_date1 != '0000-00-00' AND DATE(customers.appointment_date1) >= CURDATE()) THEN customers.appointment_date1
WHEN (customers.appointment_date2 != '0000-00-00' AND DATE(customers.appointment_date2) >= CURDATE()) THEN customers.appointment_date2
WHEN (customers.appointment_date3 != '0000-00-00' AND DATE(customers.appointment_date3) >= CURDATE()) THEN customers.appointment_date3
WHEN (customers.appointment_date4 != '0000-00-00' AND DATE(customers.appointment_date4) >= CURDATE()) THEN customers.appointment_date4
END as appointment
ORDER BY appointment ASC
But it's wrong, it doesn't work correctly.
Anyone can help?
Thanks
I'd use nested mysql if() functions in select clause, like :
select *
from(
select if(date1<date2&&date1>curdate(),date1,
if(date2<date3&&date2>curdate(),date2,
if(date3>curdate(),date3, 'nothing')
)
) as date
from dates
) as dates
order by dates.date desc;
EDIT : as per Zika's comment
SELECT IF(LEAST(
IFNULL(date1,'0000-00-00'),
IFNULL(date2,'0000-00-00'),
IFNULL(date3,'0000-00-00')
)!='0000-00-00',
LEAST(
IFNULL(date1,'0000-00-00'),
IFNULL(date2,'0000-00-00'),
IFNULL(date3,'0000-00-00')
),
'aucune date'
)
FROM dates;
I have a working mysql query, but I can not get it work with postgres. This is the query (I already changed date format to to_char
SELECT country as grouper, date(users.created_at) as date,
to_char(users.created_at, '%Y-%m') as date_group,
count(id) as total_count
FROM "users"
WHERE (users.created_at >= '2011-12-01')
AND (users.created_at <= '2014-02-11')
GROUP BY grouper, date_group
ORDER BY date ASC
I am getting the error:
PG::Error: ERROR: column "users.created_at" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT country as grouper, date(users.created_at) as date, t...
Thank for your help.
SELECT country as grouper, date(MIN(users.created_at)) as date,
to_char(MIN(users.created_at), '%Y-%m') as date_group,
count(id) as total_count
FROM "users"
HAVING (users.created_at >= '2011-12-01')
AND (users.created_at <= '2014-02-11')
GROUP BY grouper, date_group
ORDER BY date ASC
MySQL is not very strict. In standard conform SQL all column values have to use an aggrate function (SUM, COUNT, MAX, MIN) on non-grouping fields - when using GROUP BY.
Honestly said, I am not entirely sure about data_group in the GROUP BY; can it be dropped?
Also note that I have switched WHERE with a HAVING.
You should use every selected column in GROUP BY section.
SELECT country as grouper, to_char(created_at, '%Y-%u') as date_group, count(id) as total_count
FROM "users"
WHERE created_at >= '2013-10-01'
AND created_at <= '2014-02-11'
GROUP BY grouper, date_group
ORDER BY date_group ASC