What is the error in my query? - php

in below query it returns 12 record while query in from clause (as t) returns 18 record, can anyone help what is the issue in this query?
SELECT count(abc.id) as total_this_month,t.*
FROM email_details abc
JOIN
(SELECT count(email_details.id) as total_emails,MAX(`email_details`.email_date) as email_date1, `email_details`.* FROM (`cld_users` join email_details on email_details.fk_user_id = cld_users.id) GROUP BY `email_details`.`email_title` ORDER BY `email_details`.`email_date` DESC) as t
ON abc.email_title = t.email_title
where (MONTH(abc.email_date)=MONTH(NOW()) AND YEAR(abc.email_date)=YEAR(NOW()))
group by t.email_title
ORDER BY t.`email_date` DESC

In your query, you specify
where (MONTH(abc.email_date)=MONTH(NOW()) AND YEAR(abc.email_date)=YEAR(NOW()))
But in the subquery (the one returning 18 results), you have 6 emails with a month that is not december 2014. There's no way that those emails can be returned by a query that explicitly excludes them.
You want those emails as well so you get 18 results ? Remove the WHERE clause excluding them:
SELECT Count(abc.id) AS total_this_month,
t.*
FROM email_details abc
JOIN (SELECT Count(email_details.id) AS total_emails,
Max(`email_details`.email_date) AS email_date1,
`email_details`.*
FROM (`cld_users`
JOIN email_details
ON email_details.fk_user_id = cld_users.id)
GROUP BY `email_details`.`email_title`
ORDER BY `email_details`.`email_date` DESC) AS t
ON abc.email_title = t.email_title
GROUP BY t.email_title
ORDER BY t.`email_date` DESC
Starting from there, if you want to count the emails from the current month, simply replace:
SELECT Count(abc.id) AS total_this_month,
with
SELECT SUM(CASE WHEN MONTH(abc.email_date)=MONTH(NOW()) AND YEAR(abc.email_date)=YEAR(NOW()) THEN 1 ELSE 0 END) AS total_this_month,

Related

Get data if insert are in the same second

I have this table :
id idm date_play
1 5 2017-08-23 12:12:12
2 5 2017-08-23 12:12:12
3 6 2017-08-23 12:14:13
I want to identify if user has more then one insert in the same second. In the case describe I want to get the user id that is 5.
I tried like this :
SELECT `idm`, MAX(`s`) `conseq` FROM
(
SELECT
#s := IF(#u = `idm` AND (UNIX_TIMESTAMP(`date_play`) - #pt) BETWEEN 1 AND 100000, #s + 1, 0) s,
#u := `idm` `idm`,
#pt := UNIX_TIMESTAMP(`date_play`) pt
FROM table
WHERE date_play >= '2017-08-23 00:00:00'
AND date_play <= '2017-08-23 23:59:59'
ORDER BY `date_play`
) AS t
GROUP BY `idm`
Can you help me please ? Thx in advance and sorry for my english.
Assuming your dates are accurate down to the second level, you can do this with a single aggregation:
select idm
from t
group by idm
having count(*) > count(distinct date_play);
If date_play has fractional seconds, then you would need to remove those (say by converting to a string).
If you want the play dates where there are duplicates:
select idm, date_play
from t
group by idm, date_play
having count(*) >= 2;
Or, for just the idms, you could use select distinct with group by:
select distinct idm
from t
group by idm, date_play
having count(*) >= 2;
(I only mention this because this is the only type of problem that I know of where using select distinct with group by makes sense.)
If you want all the rows that are duplicated, I would go for exists instead:
select t.*
from t
where exists (select 1
from t t2
where t2.idm = t.idm and t2.date_play = t.date_play and
t2.id <> t.id
);
This should have reasonable performance with an index on (idm, date_play, id).
If your table is called mytable, the following should work:
SELECT t.`idm`
FROM mytable t INNER JOIN mytable t2
ON t.`idm`=t2.`idm` AND t.`date_play`=t2.`date_play` AND t.`id`!=t2.`id`
GROUP BY t.`idm`
Basically we join the table with itself, pairing records that have the same idm and date_play, but not the same id. This will have the effect of matching up any two records with the same user and datetime. We then group results by user so you don't get the same user id listed multiple times.
Edit:
Gordon Linoff and tadman's suggestions led me to this probably much more efficient query (credit to them)
SELECT t.`idm`
FROM mytable t
GROUP BY t.`date_play`
HAVING COUNT(t.`id`)>1

Mysql group by and count attempts on seperate column

I have a mySQL query that groups results by quiz attempt ID:
SELECT *
FROM quiz_log
WHERE archived = 0
GROUP BY quiz_attempt_id
ORDER BY quiz_attempt_id ASC
My question is how do I now count up the attempts in the by app_user_id. The app_user_id = 150 appears three times, so I need another column with the number 1 on the first line, 2 on the 3rd line and 3 on the 19th line.
You can use a correlated query:
SELECT t.*,
(SELECT count(distinct s.quiz_attempt_id) FROM quiz_log s
WHERE s.app_user_id = t.app_user_id
AND s.timestamp <= t.timestamp) as Your_Cnt
FROM quiz_log t
WHERE ....

Subquery executes more than one row and my query is different

SELECT enquiry.*,
(SELECT comm
from comments
where enquiry.id = comments.enquiryId
order by time DESC
) as comm
FROM enquiry
where id='110' AND cmpId='3'
when i want to execute more than one row by removing limit it say "subquery executes more than one row"
Please help
Your subquery is called a scalar subquery, meaning that it must have one column and at most one row. One simple method is to put the results in multiple rows, using JOIN:
SELECT e.*, c.comments
FROM enquiry e JOIN
comments c
ON e.id = c.enquiryId
where e.id = 110 AND e.cmpId = 3;
Or you can put the subquery in the from clause (as below), which is similar to join condition.
SELECT enquiry.*, comm.comm
FROM enquiry,
(SELECT comm
from comments
where enquiry.id = comments.enquiryId
order by time DESC
) as comm
where id='110' AND cmpId='3'
As the relation between enquiry & comments is 1 to many (as appears)
You need to add GROUP_CONCAT() functions to group all comments as follows:
SELECT enquiry.*,
(SELECT GROUP_CONCAT(comm)
from comments
where enquiry.id = comments.enquiryId
order by time DESC
) as comm
FROM enquiry
where id='110' AND cmpId='3'

How to retrieve the last record in each group

I am trying to get data from my table using group by . using group by works correctly but i need to take only last inserted item of every group but its not work. my query always return first item of each group.
my query
SELECT id,type,userId,performDate,eventId FROM
`user_marker` where `eventId`='842' and DATE_FORMAT(from_unixtime(performDate),'%Y%c%d')
=DATE_FORMAT(now(),'%Y%c%d')
and `visibility`='1'GROUP BY type ORDER BY id DESC
Please try
SELECT a.* FROM ( SELECT id,type,userId,performDate,eventId FROM
`user_marker` where `eventId`='842' and DATE_FORMAT(from_unixtime(performDate),'%Y%c%d')
=DATE_FORMAT(now(),'%Y%c%d') and `visibility`='1' ORDER BY id DESC ) as a GROUP BY a.type
You can try as per below-
SELECT b.id,b.type,b.userId,b.performDate,b.eventId
FROM user_marker b
JOIN (SELECT `type`,MAX(performDate)
FROM user_marker
WHERE `eventId`='842' AND DATE(FROM_UNIXTIME(performDate))=CURDATE() AND `visibility`='1'
GROUP BY `type`) a ON a.type=b.type AND a.performDate=b.performDate
ORDER BY b.`type`;

Is it possible to make query result in running another query? [duplicate]

This question already has an answer here:
Using results from one MySQL query in another query in a PHP Envirnment
(1 answer)
Closed 10 years ago.
I have this query:
$aircraft_query = "SELECT COUNT(aircraft) as total, aircraft FROM db_pireps WHERE pilotid = $pilotid GROUP BY aircraft ORDER BY total DESC LIMIT 6";
$planes = DB::get_results($aircraft_query);
And using a foreach statement, I can generate rows in a table to show aircrafts flown by a pilotid. However, I'd like now the RESULT to link to another table and extract data from there, such as aircraft type, in a fullname column.
I have this: <?php echo $aircraft->fullname; ?> but that data is in a different table. So, if aircraft was 30, it would access 30th record in db_aircrafts table and take the fullname column. How can I do this? Is it even possible?
What you need is called a table JOIN (also see JOIN in MySQL manual):
SELECT
COUNT(a.aircraft) as total
, a.aircraft
, b.fullname AS aircraft_name
FROM db_pireps AS a
JOIN db_aircraft AS b
ON a.aircraft = b.id
WHERE pilotid = {$pilotid}
GROUP BY aircraft
ORDER BY total DESC
LIMIT 6
You should use SQL Joins.
SELECT COUNT(A.aircraft) as total, A.aircraft, B.fullname
FROM db_pireps A
LEFT JOIN pilot_data_table B ON A.pilotid = B.id
WHERE A.pilotid = $pilotid
GROUP BY A.aircraft ORDER BY total DESC LIMIT 6

Categories