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

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;

Related

Why this WHERE condition that have to select records in a specified timeframe is not working as expected?

I am not so into database and I have the following problem working on this MySql query:
SELECT
CCMD.id AS crop_calendar_message_details_id,
CCMD.broadcasting_start_date AS broadcasting_start_date,
CCMD.broadcasting_end_date AS broadcasting_end_date,
CCMD.creation_date AS creation_date,
CCM.id AS message_id,
CCM.content_en AS content_en,
IFNULL(CCMN.content, CCM.content_en) AS content,
CCMN.audio_link AS audio_link,
CCMD.crop_action_details_id AS crop_action_details_id
FROM CropCalendarMessageDetails AS CCMD
INNER JOIN CropCalendarMessage AS CCM
ON CCMD.crop_calendar_message_id = CCM.id
LEFT JOIN CropCalendarMessageName AS CCMN
ON CCMN.crop_calendar_message_id = CCM.id AND CCMN.language_id = :language_id
INNER JOIN CropActionDetails AS CAD
ON CCMD.crop_action_details_id = CAD.id
WHERE
CCMD.commodity_id = 10
AND
CCMD.country_id = 2
AND
CAD.id = :cad_id
AND
CCMD.broadcasting_start_date >= CURDATE()
AND
CURDATE() <= CCMD.broadcasting_end_date
ORDER BY CCMD.broadcasting_start_date
I have some records that have the following fixed values for thes date fields:
CCMD.broadcasting_start_date = 22/12/2018 23:59:00
CCMD.broadcasting_end_date = 30/05/2018
So in theory my query should skip these values because I have set this section on my WHERE clause:
AND
CCMD.broadcasting_start_date >= CURDATE()
AND
CURDATE() <= CCMD.broadcasting_end_date
The problem is that these records are returned by my query so this dates filter condition is not working.
Why? What is wrong? What am I missing? How can I fix it?
When dealing with date/time values and querying, I personally have always tried to apply >= and < the boundaries. For example, if you wanted something for All activity within March, 2018, I would do
where '2018-03-01' <= DateTimeField
AND DateTimeField < '2018-04-01'
By doing greater or equal to the start of just a date, you get from midnight all the way through the date period. As for the ending date, I always go LESS than the following day (hence April 1st). So I get everything up to Mar 31 at 11:59:59pm.
This way you also dont need to mess with date conversion functions just to ensure something is on the same day or time-portions thereof.
Might this help in resolving the date/time considerations of your query.

Retention Rate with MySQL

I try to calculate the retention rate with mysql and start with this one:
SELECT
s_order.ordertime,
DATE_SUB(future_orders.ordertime, INTERVAL 90 DAY),
count(distinct s_order.userID) as active_users,
count(distinct future_orders.userID) as retained_users
FROM s_order
LEFT JOIN s_order as future_orders on
s_order.userID = future_orders.userID
AND s_order.ordertime = DATE_SUB(future_orders.ordertime, INTERVAL 90 DAY);
This does not work - I get all users are active and therefore I added DATE_SUB(future_orders.ordertime, INTERVAL 90 DAY), to the selection criteria to see what is going on. However it returns NULL - but why?
As a reference I did take a look at this explanation:
https://www.periscopedata.com/blog/how-to-calculate-cohort-retention-in-sql.html
My table has a structure like
s_orders:
ID | userID | ordertime
I would expect a result how many different users have ordered something in general and how many have ordered something again in the last 90 days, to get the retention of the customers.
Does anybody know what am I doing wrong in MySQL?
DATE_SUB() returns null when the date value is null, so that probably why. Because you are LEFT JOIN-ing, the future_orders record can be null/non-existing

datetime select with -15 minute interval showing wrong result

For a room reservation page I'm making a query for entries among 3 tables. Datetime values are in one table, another table keeps the info if the room key has been checked out. And another table keeps the reservation information. If current time has past start of reservation time at least 15 minutes and the key has not been checked out, the entry should get deleted. Problem is, it deletes also future reservations, where the start time of the reservation has not past yet. My query looks like this.
SELECT dt.field_reservation_datetime_value
, dt.entity_id
, co.field_reservation_checked_out_value
, co.entity_id
, res.reservation_id
FROM field_data_field_reservation_datetime dt
JOIN field_data_field_reservation_checked_out co
ON co.entity_id = dt.entity_id
JOIN studyroom_reservation res
ON res.reservation_id = co.entity_id
WHERE co.field_reservation_checked_out_value = 0
AND DATE (dt.field_reservation_datetime_value) <= NOW() - INTERVAL 15 MINUTE
Right now it is 9:52am, this shouldn't be showing up for the next 2 hours and 38 minutes. What I get is this:
Any idea what I may doing wrong?
edit: table alias added and screenshot
Solved it with following code
SELECT dt.*, co.*, res.*
FROM field_data_field_reservation_datetime AS dt
JOIN field_data_field_reservation_checked_out AS co
ON co.entity_id = dt.entity_id
JOIN studyroom_reservation as res
ON res.reservation_id = co.entity_id
WHERE co.field_reservation_checked_out_value = 0
AND ((dt.field_reservation_datetime_value)
<= DATE_FORMAT(NOW() - INTERVAL 15 MINUTE,'%Y-%m-%d %H:%i:%s'))

SQL, select entries older than 30 days, filter entries older than 30 days that have entries within the last 30 days

Not the best worded question I'll admit. I am trying to write a query to select entries older than 30 days. I have this so far
SELECT farm_list.customer_id, data_stored.`timestamp`
FROM farm_db.data_stored data_stored
INNER JOIN farm_db.farm_list farm_list
ON (data_stored.farm_code = farm_list.farm_code)
WHERE data_stored.`timestamp` >= CURDATE() - 30
GROUP BY farm_list.customer_id
This works to select all the entries older than 30 days and group them by customer.
So some customers have entries within the last 30 days AND older than 30 days. I would like to exclude those customers. The aim of the query is to highlight inactive customers. The data_stored table is updated every time there is customer activity on the server.
If I've been unclear, please just ask and I'll try to clarify. Any help would be much appreciated.
What you are saying is that the most recent timestamp is older than 30 days for a customer. So, let's implement this:
SELECT farm_list.customer_id, max(data_stored.`timestamp`) as maxts
FROM hathor_hb.data_stored data_stored INNER JOIN
farm_db.farm_list farm_list
ON (data_stored.farm_code = farm_list.farm_code)
GROUP BY farm_list.customer_id
HAVING maxts <= CURDATE() - 30;

MYSQL Inner Join & Get value from Subquery

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)