WHERE clause behaving in the wrong way - mysql

i want to create a weekly report using a php script. in the mysql query of this, i want to take out tables that functioned during the last week by using its timestamp in the meantime get the other values(especially the counts of unique users and overall users) since the creation date of those tables. but at the moment its returning incorrect data in terms of counts where the counts are given only within the last week not since the creation of project.
this happens inside a loop so for the example query im using table table_1
QUERY
SELECT DISTINCT b.ID, name, accountname, c.accountID, status,
total_impr, min(a.timestamp), max(a.timestamp),COUNT(DISTINCT userid)
AS unique_users,COUNT(userid) AS overall_users
FROM table_1 a INNER JOIN logs b on a.ID = b.ID INNER JOIN
accounts c on b.accountID = c.accountID
WHERE a.timestamp > DATE_ADD(NOW(), INTERVAL -1 WEEK

Related

GROUP BY Precedence in MySQL

I have two tables; one is called rules and the other data. The Rules table holds events, which have a description, id and date_created and is simply used to categorize events.
The data table has a date and id column; This stores the actual dates of an event, as events can span up to months long in dates.
My issue is this: I wish to select everything from data and group it by date, so each date is represented only once. However, the event with the most recent creation date should have precedence if there is a collision, i.e. two events happen on the same day. Here is what I've tried, which doesn't offer control over date_created:
SELECT d.date, r.description FROM data d LEFT JOIN rules r ON d.id = r.id GROUP BY date ORDER BY d.date
I haven't included date_created yet because I'm stuck, and not sure where it should go in the query to get the desired effect. Any ideas would be greatly appreciated!
From your question it seems to me that at first you need to select maximum date of event creation and then using subquery you can desired result:
SELECT a.date, b.description
FROM data a
INNER JOIN (
SELECT id, description,MAX(date_created) as mdate
FROM rules
GROUP BY id,description
) b ON a.id = b.id AND a.date = b.mdate

Mysql Query where max(time) less than today

I have two tables, the first table ( job ) stores the data and the second table ( job_locations ) stores the locations for each job, I'm trying to show the number of jobs that job locations are less than today
I use the DateTime for the Date Column
unfortunately, the numbers that appear after test the next code are wrong
My code
SELECT *
FROM `job`
left join job_location
on job_location.job_id = job.id
where job_location.cutoff_time < CURDATE()
group by job.id
Please help me to write the working Query.
I think you need to rephrase your query slightly. Select a count of jobs where the cutoff time is earlier than the start of today.
SELECT
j.id,
COUNT(CASE WHEN jl.cutoff_time < CURDATE() THEN 1 END) AS cnt
FROM job j
LEFT JOIN job_location jl;
ON j.id = jl.job_id
GROUP BY
j.id;
Note that the left join is important here because it means that we won't drop any jobs having no matching criteria. Instead, those jobs would still appear in the result set, just with a zero count.
As a note, you can simplify the count (in MySQL). And, assuming that all jobs have at least one location, you don't need a JOIN at all. So:
SELECT jl.job_id, sum( jl.cutoff_time < CURDATE() )
FROM job_location jl
GROUP BY jl.job_id;
If this is not correct (and you need the JOIN), then the condition on the date should go in the ON clause:
SELECT jl.job_id, COUNT(jo.job_id)
FROM job LEFT JOIN
job_location jl
ON jl.job_id = j.id AND jl.cutoff_time < CURDATE()
GROUP BY jl.job_id;

SQL Join with data associated to dates

Currently I have a simple SQL request to get aall group departure date and the associated group size (teamLength) between 2 dates but it doesn't work properly.
SELECT `groups`.`departure`, COUNT(`group_users`.`group_id`) as 'teamLength'
FROM `groups`
INNER JOIN `group_users`
ON `groups`.`id` = `group_users`.`group_id`
WHERE departure BETWEEN '2017-03-01' AND '2017-03-31'
In fact, if I have more than 1 group between the 2 dates, only 1 date will be recovered in association with the total number of teamLength.
For exemple, if I have 2 groups in the same interval with, for group 1, 2 people and for group 2, 1 people, the result will be:
Here are 2 screenshots of the current state of my groups and group_users tables:
Is it even possible to do what I want in only 1 SQL request ? Thanks
In addition to what jarlh commented (JOIN with ON). Don't ever group data without an explicit GROUP BY. I don't know why MYSQL still allows this...
Change your query to something like this and you should get the result you are looking for. Currently, the other departure dates get lost in the aggregation.
SELECT
groups.departure,
COUNT(1) as team_length
FROM
groups
INNER JOIN group_users
ON groups.id = group_users.group_id
WHERE
groups.departure BETWEEN '2017-03-01' AND '2017-03-31'
GROUP BY
groups.departure
I think that you have a syntax issue in your query. You are missing the ON statement so your database could be trying to get a cartesian product since there is no join clause.
SELECT `groups`.`departure`, COUNT(`group_users`.`id`) as 'teamLength'
FROM `groups`
INNER JOIN `group_users` ON `groups`.`id` = `group_users`.`group_id`
WHERE departure BETWEEN '2017-03-01' AND '2017-03-31'
GROUP BY `groups`.`departure`
You also are missing the GROUP BYclause which is not mandatory in all RDBS but it is a good practice to set it.

MySQL GROUP BY w/ ORDER BY not having desired result

I have a query that attempts to retrieve IDs of people, but only if those people have more than one address. I'm also checking that the last time I called them was at least 30 days ago. Finally, I'm trying to order the results, because I want to pull up results with the oldest last_called datetime:
SELECT
p.id,
COUNT(*) AS cnt
FROM
people p
LEFT JOIN addresses a
ON p.id = a.id
WHERE p.last_called <= DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY p.id
HAVING COUNT(*) > 1
ORDER BY p.last_called ASC
LIMIT 25
Right now, the results are not excluding people with only one address. I haven't even got to the point where I know if the sort order is correct, but right now I'd just like to know why it is that my query isn't pulling up results where there is at least 2 addresses for the person.
If you don't want to include people with no address then I would recommend using INNER JOIN instead of LEFT JOIN and DISTINCT to get distinct address ids
(just in case if you have duplicate mappings), e.g.:
SELECT
p.id,
COUNT(DISTINCT(a.id)) AS cnt
FROM
people p
JOIN addresses a
ON p.id= a.peopleid
WHERE p.last_called <= DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY p.id
HAVING COUNT(DISTINCT(a.id)) > 1
As far as Ordering is concerned, MySQL evaluates GROUP BY before ordering the results and hence, you need to wrap the query inside another query to get the ordered results.
Update
Instead of joining on aid, you need to join on peopleId of an address record to get the people record.

MySQL to generate daily profile views reports with filled gaps

I'm about to plot daily profile views in chart.js. I have two table one for track every day profile visit named "stats_profile_views" and second one carries all date of an year named "calendar"
I would like to show last 7 days profile views when logged in each vendor.
Tried following query,
SELECT datefield AS DATE ,`id`, `vendor_id`, `view_date`,IFNULL(view_count,0) AS view_count
FROM (`stats_profile_views` pv)
RIGHT JOIN bp_calendar ON (DATE(view_date) = bp_calendar.datefield)
WHERE `vendor_id` = '110'
AND bp_calendar.datefield BETWEEN DATE_SUB(NOW(), INTERVAL 7 DAY) AND NOW()
GROUP BY DATE
ORDER BY `view_date` asc
I like to get past 7 days records filled with view_count zero for non-available records in "stats_profile_views" table. But when apply WHERE vendor_id = '110' it fails to return such record and gives only 3 records related with vendor_id = '110'. But it work great without vendor_id filter.
How can I get last 7 days records filled with view_count as zero when filter using vendor_id. Anybody guide me to a solution please.
SELECT
c.datefield AS DATE
, pv.id
, pv.vendor_id
, pv.view_date
, IFNULL(pv.view_count, 0) AS view_count
FROM bp_calendar c
LEFT JOIN stats_profile_views pv ON (DATE(pv.view_date) = c.datefield)
AND pv.vendor_id = '110'
WHERE c.datefield BETWEEN DATE_SUB(NOW(), INTERVAL 7 DAY) AND NOW()
ORDER BY
pv.view_date ASC
When using outer joins the where clause MUST be careful not to override the unmatched rows, otherwise you get the effect of an inner join instead. That's what happened in your original query; because EVERY row is required to have a vendor_id = '110' but an unmatched date cannot have any vendor_id.
Additionally it generally helps to write the query FROM (the table with the all the rows) LEFT JOIN (table with gaps in it). Then include the extra conditions of the left joined table as extra join conditions instead of the where clause.
If you want to group the results then you need to indicate what it is you are attempting to do. Perhaps summing the view_counts? However if you are intending to do that then you would not include columns like id in the result.
Also, please, include the table alias in EVERY reference to column.