MYSQL Inner Join & Get value from Subquery - mysql

OK, I am trying to compare two tables and then input a list from a third of names to produce a totals of values for the prior 10 days. The query runs but gives me a NULL result and only one result. If I remove the DATE_ADD and replace it with a real date from the database and put in a value for the left clause instead of using the subquery I do get what I am looking for that specific date. What I would like to do is create a list of the names with the values for that day and the last 10 days. I am sure I am not doing this right so any help is appreciated as I am fairly new to this. Simple queries are easy but putting something complex like this is new to me.
select sum(t.price) from td.trs as t
inner join td.order as o on o.trsid=t.id
inner join pts.product as p on p.id=o.grp_id
where t.invoice_date=DATE_ADD(CURRENT_DATE(),INTERVAL 10 DAY)
and left(t.mfgid,3) IN (select name from name.list);

change
where t.invoice_date=DATE_ADD(CURRENT_DATE(),INTERVAL 10 DAY)
to
where t.invoice_date >= DATE_ADD(CURRENT_DATE(),INTERVAL -10 DAY)

You are probably not getting any results because you are doing DATE_ADD to the CURRENT_DATE(), which will give you a date 10 days in the future. If you want to get all items for last 10 days, use
WHERE t.invoice_date BETWEEN CURRENT_DATE() AND DATE_SUB(CURRENT_DATE(), INTERVAL 10 DAY)

Related

MYSQL updating a table containing a join and subquery

I am relatively new to SQL, i am trying to update monthly salary based on employees working for a certain duration, the query displays the data using info from the person and employee table but it won't update, i keep getting a 'operand should contain 1 column' error? How would i go about displaying all the data and be able to update the monthly_salary column as well? Thanks.
UPDATE employee ep set monthly_salary = monthly_salary*1.15 = all(
SELECT p.person_id, p.name_first, p.name_last, ep.monthly_salary, ep.start_date, curdate() as today_date,
TIMESTAMPDIFF(month,ep.start_date,curdate()) as duration_months
FROM employee ep
INNER JOIN person p ON ep.person_id = p.person_id having duration_months > 24);
query result
I want this expected result but the monthly salary hasn't been updated yet, is it possible to display this and update the monthly_salary?
You are not able to do both in a single query. Typically one would run a "select query" to inspect if the desired logic appears correct, e.g.
SELECT
p.person_id
, p.name_first
, p.name_last
, ep.start_date
, curdate() as today_date
, TIMESTAMPDIFF(month,ep.start_date,curdate()) as duration_months
FROM employee ep
INNER JOIN person p ON ep.person_id = p.person_id
WHERE ep.start_date < curdate() - INTERVAL 24 MONTH
;
In that query the important piece of logic is the where clause which seeks out any employees with a start date earlier than today - 24 months.
If that logic is correct, then apply the same logic in an "update query":
UPDATE employee ep
SET monthly_salary = monthly_salary*1.15
WHERE ep.start_date < curdate() - INTERVAL 24 MONTH
;
Syntax notes:
you cannot string multiple conditions together using multiple equality operators (monthly_salary = monthly_salary*1.15 = all(...) there are 2 = signs in that
x = all() requires that all values returned by a subquery will equal x
the having clause is NOT just a substitute for a where clause. A having clause is designed for evaluating aggregated data e.g. having count(*) > 2
Finally, while it was inventive to use the having clause, what you were doing was gaining access to the alias 'duration_months', so you could simply have done this instead:
where TIMESTAMPDIFF(month,ep.start_date,curdate()) > 24
BUT this is not a good way to filter information because it requires running a function on every row of data before a decision can be reached. This has he effect of making queries slower. Compare that to the following:
WHERE ep.start_date < curdate() - INTERVAL 24 MONTH
ep.start_date is not affected by any function, and curdate() - INTERVAL 24 MONTH is just one calculation (not done every row). So this is much more efficient (also known as "sargable").

MySQL Query Multiple Joins duplicating data for each row? JIRA Database

I'm trying to pull the sum time worked for each user in a certain group over the next 30 days. I am not great at MySQL, so a lot of this may be wrong. This is from a JIRA database.
SELECT DISTINCT cu.display_name AS 'Associate', sum(wl.timeworked/3600) AS '30 Days'
FROM worklog AS wl, cwd_user AS cu
INNER JOIN cwd_membership AS cm
ON cu.directory_id=cm.directory_id
AND cu.lower_user_name=cm.lower_child_name
AND cm.membership_type='GROUP_USER'
INNER JOIN worklog
ON worklog.AUTHOR = cu.user_name
WHERE cm.lower_parent_name='atl_servicedesk_it_agents' AND wl.STARTDATE BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 30 DAY)
ORDER BY cu.last_name;
Right now it just displays the first users name with a sum total of everything in the time worked for everyone. That is obviously not what I want... If I remove the sum from timeworked it shows about half of the users from that group, but each user has a value of 16 hours for timeworked, which is incorrect. Only one user has any value for the next 30 days and it is for 16 hours, so for some reason it is duplicating this information.
Any ideas?
Got it working by taking out the INNER JOINs.
SELECT cwd_user.display_name AS 'Associate', sum(worklog.timeworked/3600) AS '30 Days'
FROM worklog, cwd_user,cwd_membership
WHERE worklog.AUTHOR = cwd_user.user_name
and cwd_user.directory_id = cwd_membership.directory_id
and cwd_user.lower_user_name = cwd_membership.lower_child_name
and cwd_membership.membership_type = 'GROUP_USER'
and cwd_membership.lower_parent_name = 'atl_servicedesk_it_agents'
and worklog.STARTDATE BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 60 DAY)
GROUP BY cwd_user. display_name
ORDER BY cwd_user.last_name;

pulling records from mysql where the difference between 2 dates is greater than 8 days

According to this documentation from my understanding using INTERVAL 8 DAY will return any records greater than 8 days.
In my statement $moztimestampnow is the current date in this format 2015-05-21 and moztimestamp pertains to the column in the DB that contains the other earlier date in which I need to calculate with.
I am not sure if I am able to use moztimestamp as the column name in this statement and it is not working.
How do I get the difference in days?
$moztimestampnow = date('Y-m-d');
SELECT *,DATEDIFF('$moztimestampnow',moztimestamp) INTERVAL 8 DAYS FROM backlinks WHERE user_id = '$user_id' LIMIT 10
First, you a misinterpreting the documentation. The interval keyword is for adding values to dates. If you want to filter data, you need to use the where clause.
In your case, the best where clause looks like this:
SELECT bl.*, DATEDIFF('$moztimestampnow', moztimestamp)
FROM backlinks bl
WHERE user_id = '$user_id' and
moztimestamp <= DATE_SUB(CURDATE(), INTERVAL 8 DAY)
LIMIT 10
This can take advantage of an index on backlinks(user_id, moztimestamp). In addition, you probably should have an ORDER BY clause. That is expected when using LIMIT.
Your syntax doesn't make sense. Try something like:
SELECT *
FROM backlinks
WHERE DATE_SUB(moztimestamp, INTERVAL 8 DAY) > '$moztimestampnow'
AND user_id = '$user_id'
LIMIT 10
I don't follow your objective, so you may have to change the order and direction in the first WHERE clause.

MySQL cumulative sum grouped by date

I know there have been a few posts related to this, but my case is a little bit different and I wanted to get some help on this.
I need to pull some data out of the database that is a cumulative count of interactions by day. currently this is what i have
SELECT
e.Date AS e_date,
count(e.ID) AS num_interactions
FROM example AS e
JOIN example e1 ON e1.Date <= e.Date
GROUP BY e.Date;
The output of this is close to what I want but not exactly what I need.
The problem I'm having is the dates are stored with the hour minute and second that the interaction happened, so the group by is not grouping days together.
This is what the output looks like.
On 12-23 theres 5 interactions but its not grouped because the time stamp is different. So I need to find a way to ignore the timestamp and just look at the day.
If I try GROUP BY DAY(e.Date) it groups the data by the day only (i.e everything that happened on the 1st of any month is grouped into one row) and the output is not what I want at all.
GROUP BY DAY(e.Date), MONTH(e.Date) is splitting it up by month and the day of the month, but again the count is off.
I'm not a MySQL expert at all so I'm puzzled on what i'm missing
New Answer
At first, I didn't understand you were trying to do a running total. Here is how that would look:
SET #runningTotal = 0;
SELECT
e_date,
num_interactions,
#runningTotal := #runningTotal + totals.num_interactions AS runningTotal
FROM
(SELECT
DATE(eDate) AS e_date,
COUNT(*) AS num_interactions
FROM example AS e
GROUP BY DATE(e.Date)) totals
ORDER BY e_date;
Original Answer
You could be getting duplicates because of your join. Maybe e1 has more than one match for some rows which is inflating your count. Either that or the comparison in your join is also comparing the seconds, which is not what you expect.
Anyhow, instead of chopping the datetime field into days and months, just strip the time from it. Here is how you do that.
SELECT
DATE(e.Date) AS e_date,
count(e.ID) AS num_interactions
FROM example AS e
JOIN example e1 ON DATE(e1.Date) <= DATE(e.Date)
GROUP BY DATE(e.Date);
I figured out what I needed to do last night... but since I'm new to this I couldn't post it then... what I did that worked was this:
SELECT
DATE(e.Date) AS e_date,
count(e.ID) AS num_daily_interactions,
(
SELECT
COUNT(id)
FROM example
WHERE DATE(Date) <= e_date
) as total_interactions_per_day
FROM example AS e
GROUP BY e_date;
Would that be less efficient than your query? I may just do the calculation in python after pulling out the count per day if its more efficient, because this will be on the scale of thousands to hundred of thousands of rows returned.

MySQL: Returning records from the current month and previous 3 months

I'm using PHP/MySQL booking system and i'm using a Google Line Chart to try and display the gross sales from the current month, and also the previous 3 months.
Each booking has a date in the standard phpmyadmin "date" format, so yyyy:mm:dd.
So, im looking to get 4 results from 4 queries, each query filtering out a certain month and grabbing the sum of each booking from that month.
My question is, how can i distinguish between the months in the query? How would i structure the query?
Based on the title:
select * from bookings where MONTH(CURDATE())=MONTH(booking_date);
select * from bookings where MONTH(booking_date) > MONTH(CURDATE()-INTERVAL 3 MONTH) and < MONTH(CURDATE() + INTERVAL 1 MONTH);
For simple per-month searches you can use the following:
Select * from bookings where MONTHNAME(booking_date)='July' and YEAR(booking_date)=2013;
Or:
Select * from bookings where MONTH(booking_date)=7 and YEAR(booking_date)=2013;
Also since you've already got the months, you could do this (this method requires that you maintain a table of ending dates for each month an compensate for leap year though):
select * from bookings where booking_date>'2013-06-30' AND booking_date<'2013-08-01';
In first place, excuse my english....
I know this is old thread and cant comment but, #AbsoluteƵERØ, that answer apply to the current month, in example, if i got records of July in 2013-2014-2015, the query will return the records on the month for those years.... To avoid that and using your posted code:
SELECT * FROM bookings WHERE MONTH(CURDATE()) = MONTH(booking_date) AND YEAR(CURDATE()) = YEAR(booking_date);
Note: if use the "name form" and specify the year there's no problem, like this:
SELECT * FROM bookings WHERE MONTH(CURDATE()) = MONTH(booking_date) AND YEAR(booking_date) = 2013;