MYSQL get latest job number - mysql

I have this table:
TableNumber(Int 0 to 25)|Name(varchar 100)|Project(varchar 15)|StartDate(Datetime)
1 |David |P1 |'2015-02-06 08:00:00'
2 |Sebastien |P2 |'2015-02-06 08:00:00'
1 |David |P4 |'2015-02-06 12:00:00'
2 |Sebastien |P3 |'2015-02-07 08:00:00'
And I am looking to get the latest job for each person on a set day.
I would like to have:
TableNumber(Int 0 to 25)|Name(varchar 100)|Project(varchar 15)|StartDate(Datetime)
2 |Sebastien |P2 |'2015-02-06 08:00:00'
1 |David |P4 |'2015-02-06 12:00:00'
So I want to exclude P3 since its not '2015-02-06' and I want to exclude P1 cause its not the latest job for David (its P4).
Please consider that NOW() returns '2015-02-06 15:00:00' in the following exemples.
Here is what I tried:
SELECT * FROM MyTable WHERE DATEDIFF(startdate, NOW()) = 0 ORDER BY tablenum DESC;
But this only excluded P3
So I tried this instead:
SELECT * FROM MyTable AS p WHERE DATEDIFF(p.startdate, NOW()) = 0 AND TIMEDIFF(p.startdate, NOW()) = (SELECT MAX(TIMEDIFF(p2.startdate, NOW())) FROM MyTable AS p2 WHERE p2.startdate = p.startdate) ORDER BY tablenum DESC;
But Its still doesn't exclude P1.
Anyone know how I could achieve this? BTW startdate will always be a round hour (08:00:00 or 12:00:00 or 22:00:00...)
UPDATE
Yeah since it wasn't very clear what I wanted I will clarify here:
I need to know the last project worked on by every person.
so in my table I need to know that Sebastien work on P2 on table number 2 and that David work on P4 on table number 1. I don't want P1 because its not the last project that David worked on (by last project I also include the project he is working on right now). I also want to rule out everything in the future so P3 (who is tomorrow) must not display.

The following query will provide you with the date/time of the earliest job for a given name on a given day. In the following example I assumed you want the earliest jobs of each user on 2015-02-06.
SELECT Name, min(StartDate)
FROM MyTable
WHERE StartDate >= '2015-02-06'
AND StartDate < '2015-02-07'
GROUP BY Name
Using the above query, you can trivially get the final solution:
SELECT t1.project, t2.name, t2.StartDate
FROM MyTable t1 INNER JOIN
(SELECT Name, min(StartDate)
FROM MyTable
WHERE StartDate >= '2015-02-06'
AND StartDate < '2015-02-07'
GROUP BY Name) t2 ON t1.Name = t2.Name AND t1.StartDate = t2.StartDate

Related

How to select only entries that didn't repeat before a specific date?

My issue is that I'm stuck on making a select query where I need to select only items from latest 24 hours, that don't repeat themselves on entries before those 24 hours.
Here is a table:
name
date
Mark
2021-05-27
Jake
2021-05-27
Anthony
2021-05-27
Anthony
2021-05-26
Expected output:
name
Mark
Jake
Missing element: query
Help will be appreciated.
Edit: I know that's unprecise. The real table I'm using is with full datetime type. I'm going to test your answers today and then give response.
'24 hours' is unprecise, as you do not know which dates of yesterday are actually in range of the past 24 hours. If you are ok only with today's entries only (which are less), then the following would work:
SELECT name FROM demoTable GROUP BY name HAVING MIN(date) = CURRENT_DATE;
If you actually have date and time available, then you can have:
SELECT name FROM demoTable
GROUP BY name HAVING MIN(datetime) > DATEADD(day, -1, CURRENT_TIMESTAMP);
Depending on SQL dialect, DATEADD(...) might not be available, with e. g. SQLite you'd replace it by DATETIME('now', '-1 day').
Use the below query to get the last 24 data without duplicate name
select name from tabl1 where date>getdate()-1 group by name having count(name)>0
Here getdate()-1 will give the last 1 day difference i.e. 24hr
SELECT DISTINCT t1.name
FROM tablename t1
WHERE t1.`date` = CURRENT_DATE
AND NOT EXISTS ( SELECT NULL
FROM tablename t2
WHERE t1.name = t2.name
AND t2.`date` < CURRENT_DATE );

mysql finding the sum of subgroup maximums

If I have the following table in MySQL:
date type amount
2017-12-01 3 2
2018-01-01 1 100
2018-02-01 1 50
2018-03-01 2 2000
2018-04-01 2 4000
2018-05-01 3 2
2018-06-01 3 1
...is there a way to find the sum of the amounts corresponding to the latest dates of each type? There are guaranteed to be no duplicate dates for any given type.
The answer I'd be looking to get from the data above could broken down like this:
The latest date for type 1 is 2018-02-01, where the amount is 50;
The latest date for type 2 is 2018-04-01, where the amount is 4000;
The latest date for type 3 is 2018-06-01, where the amount is 1;
50 + 4000 + 1 = 4051
Is there a way to arrive directly at 4051 in a single query? This is for a Django project using MySQL if that makes a difference; I wasn't able to find an ORM-related solution either, so figured a raw SQL query might be a better place to start.
Thanks!
Not sure for Django but in raw sql you could use a self join to pick latest row for each type based on latest date and then aggregate your results to get the sum of amounts for each type
select sum(a.amount)
from your_table a
left join your_table b on a.type = b.type
and a.date < b.date
where b.type is null
Demo
Or
select sum(a.amount)
from your_table a
join (
select type, max(date) max_date
from your_table
group by type
) b on a.type = b.type
and a.date = b.max_date
Demo
Or by using a correlated subuery
select sum(a.amount)
from your_table a
where a.date = (
select max(date)
from your_table
where type = a.type
)
Demo
For Mysql 8 you can use window functions to get you desired result as
select sum(amount)
from (select *, row_number() over (partition by type order by date desc) as seq
from your_table
) t
where seq = 1;
Demo

Interval dates from two rows MySQL

I have sample data of date in the following table on MySQL:
Start End Source
===== === ====
2017-01-01 2017-02-14 T
2017-02-17 2017-02-28 T
2017-03-10 2017-03-15 T
And I want the interval date from End date to Start date. For ex:
(2017-02-17) - 2017-02-14) = 3 days or (2017-03-10)-(2017-02-28) = 10 days
Any ideas on where to start? A lot of the reading I've done just to get interval between two dates in one row. Thank you.
you can try to use DATEDIFF() function in mysql
your answer should be
SELECT DATEDIFF(Start,End) AS DiffDate from table
you can refer to this
https://www.w3schools.com/sql/func_datediff_mysql.asp
Try the query, and let me know if it worked or not?
SET #dateDiff=NULL;SET #dateDiff2='';
SELECT diff.dateDiffR AS dateDifference FROM (
SELECT aa.`end`,aa.`start`,IF(#dateDiff IS NULL,#dateDiff:=aa.end,0) AS try,
DATEDIFF(aa.`start`,#dateDiff) AS dateDiffR,
IF(#dateDiff!=#dateDiff2,#dateDiff2:=#dateDiff,0) AS try1,
IF(DATE(#dateDiff)!=DATE(aa.end),#dateDiff:=aa.end,NULL) AS assign
FROM test.`dateCheck` aa ) diff WHERE diff.dateDiffR>0
What you are trying to achieve is finding the time difference between two consecutive rows in the same table.
You can do it that way:
SELECT t1.ID, t1.Start, t1.End,
datediff(max(t2.End ), t1.Start) as minutes
FROM t as t1 LETF JOIN t as t2 on t1.ID = t2.ID
and t2.End < t1.Start
GROUP BY t1.ID, t1.Start, t1.End
I think he wants to get the difference between enddate from row 1 and startdate from row 2, and so on.
You have another identifier ? So i think you maybe need a "LEFT JOIN" or a subquery to handle this.
SELECT a.id, a.start, a.end, b.start, b.end, b.start - a.end AS `DIFF`
FROM table1 a
INNER JOIN table1 b ON b.id = a.id -1
So you have two results in one row and you can use diff and intervall as you do for one line .
I hope this idea helps you in the right direction
you should simply use join to calculate those date
select concat(datediff(n1.start,n2.end),' ',repeat('days',1)) as days
from table_name n1
join table_name n2
on n2.end < n1.start;
see here demo
if you don't need repeat "days" than simple use this query
select datediff(n1.start,n2.end)
from your_table n1
join your_table n2
on n2.end < n1.start;

MySQL query to select distinct rows based on date range overlapping

Let's say we have a table (table1) in which we store 4 values (user_id, name, start_date, end_date)
table1
------------------------------------------------
id user_id name start_date end_date
------------------------------------------------
1 1 john 2016-04-02 2016-04-03
2 2 steve 2016-04-06 2016-04-06
3 3 sarah 2016-04-03 2016-04-03
4 1 john 2016-04-12 2016-04-15
I then enter a start_date of 2016-04-03 and end_date of 2016-04-03 to see if any of the users are available to be scheduled for a job. The query that checks for and ignores overlapping dates returns the following:
table1
------------------------------------------------
id user_id name start_date end_date
------------------------------------------------
2 2 steve 2016-04-06 2016-04-06
4 1 john 2016-04-12 2016-04-15
The issue I am having is that John is being displayed on the list even though he is already booked for a job for the dates I am searching for. The query returns TRUE for the other entry because the dates don't conflict, but i would like to hide John from the list completely since he will be unavailable.
Is there a way to filter the list and prevent the user info from displaying if the dates entered conflict with another entry for the same user?
An example of the query:
SELECT DISTINCT id, user_id, name, start_date, end_date
FROM table1
WHERE ('{$startDate}' NOT BETWEEN start_date AND end_date
AND '{$endDate}' NOT BETWEEN start_date AND end_date
AND start_date NOT BETWEEN '{$startDate}' AND '{$endDate}'
AND end_date NOT BETWEEN '{$startDate}' AND '{$endDate}');
The "solution" in the question doesn't look right at all.
INSERT INTO table1 VALUES (5,2,'steve', '2016-04-01','2016-04-04')
Now there's a row with Steve having an overlap.
And the query proposed as a SOLUTION in the question will return 'steve'.
Here's a demonstration of building a query to return the users that are "available" during the requested period, because there is no row in table1 for that user that "overlaps" with the requested period.
First problem is getting the users that are not available due to the existence of a row that overlaps the requested period. Assuming that start_date <= end_date for all rows in the table...
A row overlaps the requested period, if the end_date of the row is on or after the start of the requested period, and the start_date of the row is on or before the ed of the requested period.
-- users that are "unavailable" due to row with overlap
SELECT t.user_id
FROM table1 t
WHERE t.end_date >= '2016-04-03' -- start of requested period
AND t.start_date <= '2016-04-03' -- end of requested_period
GROUP
BY t.user_id
(If our assumption that start_date <= end_date doesn't hold, we can add that check as a condition in the query)
To get a list of all users, we could query a table that has a distinct list of users. We don't see a table like that in the question, so we can get a list of all users that appear in table1 instead
SELECT l.user_id
FROM table1 l
GROUP BY l.user_id
To get the list of all users excluding the users that are unavailable, there are couple of ways we can write that. The simplest is an anti-join pattern:
SELECT a.user_id
FROM ( -- list of all users
SELECT l.user_id
FROM table1 l
GROUP BY l.user_id
) a
LEFT
JOIN ( -- users that are unavailable due to overlap
SELECT t.user_id
FROM table1 t
WHERE t.end_date >= '2016-04-03' -- start of requested period
AND t.start_date <= '2016-04-03' -- end of requested_period
GROUP
BY t.user_id
) u
ON u.user_id = a.user_id
WHERE u.user_id IS NULL
will this work?
SELECT user_id DISTINCT FROM table1 WHERE (DATEDIFF(_input_,start_date) > 0 AND
DATEDIFF(_input_,end_date) > 0) OR
(DATEDIFF(_input_,start_date) < 0);

add a column in MySQL rank by deal by day

I am just learning MySQL. I need to find out rank of deals by day. Here I am adding the corresponding MYSQL query for my requirement that currently ranks all sales highest to lowest by day. Please help me to add a column that gives the rank to the deal highest to lowest and resetting the next day.
Here is my current working query,..
single day with title, price
SELECT
DATE(order_items.created_at) AS the_day,
order_items.deal_id,
SUM(order_items.item_total) AS daily_total,
SUM(order_items.qty) AS units_sold,
deals.price,
deals.title
FROM
order_items JOIN deals ON order_items.deal_id = deals.id
WHERE
order_items.created_at >= '2016-01-01 00:00:00' AND order_items.created_at < '2016-01-30 00:00:00'
AND
order_items.status=1
AND
order_items.paid=1
GROUP BY
order_items.deal_id
ORDER BY
the_day,
daily_total DESC;
The easiest way to do is that:
Use your existing SQL - I guess you need to update your SQL, make sure any non-aggregated columns in select should be in group by as well
Use PHP to loop (1-5), it works for multiple days
If you are happy to get top 5 for a single day, you can add limit 5 at end of your SQL
If you need top 5 results for each day in multiple days in one SQL, you need to update SQL to be more complicated. And here is a hint to use row id see example:
select increment counter in mysql
OK - Since you updated your question to return top 1 result per day, this is easier:
Step 1: get each day, each deal, report:
SELECT deal_id, date(created_at) ymd, sum(item_total) daily_total, sum(qty) units_sold
FROM order_items
WHERE substr(created_at,1,7) = '2016-01'
AND status = 1
AND paid = 1
GROUP BY 1,2
Step 2: Find the best deal of each day from step 1:
SELECT aa.ymd, max(aa.daily_total) max_total
FROM (
SELECT deal_id, date(created_at) ymd, sum(item_total) daily_total, sum(qty) units_sold
FROM order_items
WHERE substr(created_at,1,7) = '2016-01'
AND status = 1
AND paid = 1
GROUP BY 1,2
) as aa
GROUP BY 1;
Please note that max(item_total) not necessary same row as max(unit_sold), so you need to choose one, and cannot run togather
Step 3: Join step 2 with step 1 and deals to find out the rest of information:
SELECT aa.*, deals.price, deal.title
FROM (
SELECT aa.ymd, max(aa.daily_total) max_total
FROM (
SELECT deal_id, date(created_at) ymd, sum(item_total) daily_total, sum(qty) units_sold
FROM order_items
WHERE substr(created_at,1,7) = '2016-01'
AND status = 1
AND paid = 1
GROUP BY 1,2
) as aa
GROUP BY 1
) as bb
JOIN (
SELECT deal_id, date(created_at) ymd, sum(item_total) daily_total, sum(qty) units_sold
FROM order_items
WHERE substr(created_at,1,7) = '2016-01'
AND status = 1
AND paid = 1
GROUP BY 1,2
) as aa ON bb.ymd = aa.ymd and bb.max_total = aa.daily_total
JOIN deals ON aa.deal_id = deals.id
ORDER BY aa.ymd, aa.max_total