I have a table employee where i want to select a row based on dates.
emp_id validation_user entry_date
-------------------------------------------------------
10 mark 2014-05-01 11:11:00
10 ann 2014-05-01 10:14:00
10 marco 2014-05-01 11:07:00
10 mark 2014-05-01 10:00:00
I would like to have the row when emp_id=10 and entry_date is less than 2014-05-01 11:11:00
This should return me only one row which is closest to 2014-05-01 11:11:00 not three rows
emp_id validation_user entry_date
-------------------------------------------------------
10 marco 2014-05-01 11:07:00
my select statement returns me 3 rows:
SELECT *
FROM emp
where entry_date < "2014-05-01 11:11:00"
Since there is no row_number in MySQL, you can achieve this with limit and order by :
SELECT *
FROM emp
where entry_date < "2014-05-01 11:11:00"
order by entry_date desc
limit 1
What we do here is order by entry_date to make sure the first row is really the first one we want, then we specify to limit the query to 1 value.
We specify to order in descending order as we want the highest value that is lower then the specified date.
Related
I want to keep track of users logged in every day between two dates.
Let's say I have a table my_table like this:
user_id
login_datetime
1
2021-10-02 10:00:00
1
2021-10-02 12:00:00
2
2021-10-02 12:20:00
1
2021-10-03 17:00:00
1
2021-10-04 22:00:00
2
2021-10-04 23:00:00
and given date range is from '2021-10-02' to '2021-10-04'.
I want to get user_id = 1 in this case, because user_id = 2 is not logged in at '2021-10-03'
result
user_id
login_date
1
2021-10-02
1
2021-10-03
1
2021-10-04
Is there any solution for this?
One approach uses aggregation:
SELECT user_id
FROM my_table
WHERE login_datetime >= '2021-10-02' AND login_datetime < '2021-10-05'
GROUP BY user_id
HAVING COUNT(DISTINCT DATE(login_datetime)) = 3; -- range has 3 dates in it
Demo
The HAVING clause asserts that any matching user must have 3 distinct dates present, which would imply that such a user would have login activity on all dates from 2021-10-02 to 2021-10-04 inclusive.
Edit:
To get the exact output in your question, you may use:
SELECT DISTINCT user_id, DATE(login_datetime) AS login_date
FROM my_table
WHERE user_id IN (
SELECT user_id
FROM my_table
WHERE login_datetime >= '2021-10-02' AND login_datetime < '2021-10-05'
GROUP BY user_id
HAVING COUNT(DISTINCT DATE(login_datetime)) = 3
);
I have 2 tables in MySQL(InnoDB). The first is an employee table. The other table is the expense table. For simplicity, the employee table contains just id and first_name. The expense table contains id, employee_id(foreign key), amount_spent, budget, and created_time. What I would like is a query that returns the percentage of their budget spent for the most recent X number of expense they've registered.
So given the employee table:
| id | first_name
-------------------
1 alice
2 bob
3 mike
4 sally
and the expense table:
| id | employee_id | amount_spent | budget | created_time
----------------------------------------------------------
1 1 10 100 10/18
2 1 50 100 10/19
3 1 0 40 10/20
4 2 5 20 10/22
5 2 10 70 10/23
6 2 75 100 10/24
7 3 50 50 10/25
The query for the last 3 trips would return
|employee_id| first_name | percentage_spent |
--------------------------------------------
1 alice .2500 <----------(60/240)
2 bob .4736 <----------(90/190)
3 mike 1.000 <----------(50/50)
The query for the last 2 trips would return
|employee_id| first_name | percentage_spent |
--------------------------------------------
1 alice .3571 <----------(50/140)
2 bob .5000 <----------(85/170)
3 mike 1.000 <----------(50/50)
It would be nice if the query, as noted above, did not return any employees who have not registered any expenses (sally). Thanks in advance!!
I'll advise you to convert datatype of created_time as DATETIME in order to get accurate results.
As of now, I've assumed that most recent id indicates most recent spents as it's what sample data suggests.
Following query should work (didn't tested though):
select t2.employee_id,t1.first_name,
sum(t2.amount_spent)/sum(t2.budget) as percentage_spent
from employee t1
inner join
(select temp.* from
(select e.*,#num := if(#type = employee_id, #num + 1, 1) as row_number,
#type := employee_id as dummy
from expense e
order by employee_id,id desc) temp where temp.row_number <= 3 //write value of **n** here.
) t2
on t1.id = t2.employee_id
group by t2.employee_id
;
Click here for DEMO
Feel free to ask doubt(s), if you've any.
Hope it helps!
If you are using mysql 8.0.2 and higher you might use window function for it.
SELECT employee_id, first_name, sliding_sum_spent/sliding_sum_budget
FROM
(
SELECT employee_id, first_name,
SUM(amount_spent) OVER (PARTITION BY employee_id
ORDER BY created_time
RANGE BETWEEN 3 PRECEDING AND 0 FOLLOWING) AS sliding_sum_spent,
SUM(budget) OVER (PARTITION BY employee_id
ORDER BY created_time
RANGE BETWEEN 3 PRECEDING AND 0 FOLLOWING) AS sliding_sum_budget,
COUNT(*) OVER (PARTITION BY employee_id
ORDER BY created_time DESC) rn
FROM expense
JOIN employee On expense.employee_id = employee.id
) t
WHERE t.rn = 1
As mentioned by Harshil, order of row according to the created_time may be a problem, therefore, it would be better to use date date type.
I have a table with logs
PERSON ID LOGDATE (DATETIME)
1000 2015-10-20 10:00:00
1000 2015-11-11 09:10:22
2001 2015-10-11 10:22:11
I need to order the data by LOGDATE -DATETIME - but with only the lowest date for each ID.
select PERSONALID, LOGDATE from TABLE group by PERSONALID order by
MIN(LOGDATE) DESC
I can GROUP by ID - ORDER BY Min DATE (each result by ID), but THE FINAL RESULT doesnt order the results by MIN DATE..
RESULT:
1000 ------------- 2015-10-20 10:00:00 (min date for ID=1000)
2001 ------------- 2015-10-11 10:22:11 (min date for ID=2001)
the right answer is:
RESULT:
2001 ------------- 2015-10-11 10:22:11 (min date for ID=2001)
1000 ------------- 2015-10-20 10:00:00 (min date for ID=1000)
what is wrong?
This should do it:
select PERSONALID, MIN(LOGDATE) as mindate
from TABLE
group by PERSONALID
order by mindate
You need to select MIN(LOGDATE), not LOGDATE. Selecting LOGDATE causes MySQL to return the value of an indeterminate record from within each group—see MySQL Handling of GROUP BY for more information.
From MySQL table I have the list amount based on the dates. I need to get the sum of amount for each date:
ex:
id type date amount
1 1 2015-01-01 100
2 1 2015-01-01 150
3 1 2015-01-02 10
4 1 2015-01-03 250
Here 2015-01-01 appears more than once.
so i need the result like
date amount
2015-01-01 200
2015-01-02 10
2015-01-03 250
My Query getting between this week start and end
SELECT * from mytable WHERE YEARWEEK(`date`) = YEARWEEK(CURRENT_DATE) AND `type` = 1 ORDER BY `date` ASC
You need a group by clause:
SELECT `date`, SUM(amount)
FROM mytable
GROUP BY `date`
I think the result should be
date amount
2015-01-01 250
2015-01-02 10
2015-01-03 250
you can use this mysql query to get that result:
Select date, sum(amount) as amount
from mytable
GROUP BY date
ORDER BY date asc
dont forget to add "ORDER BY" clause if you want the result in good order
Use GROUP BY
Use AS clause to change the column Name
SELECT `date`, SUM(amount) AS amount
FROM mytable
GROUP BY `date`
I have a schema like the following
id (INT)
Cycle_Number (INT)
Cycle_Day (INT)
Date (date)
...other columns irrelevant to the question...
How can I get the row that has the max Cycle_Day within the max Cycle_Number
For example, say I have the following data
ID Cycle_Number Cycle_Day Date
1 1 1 2011-12-01
2 1 2 2011-12-02
3 2 1 2011-12-03
4 2 2 2011-12-04
5 2 3 2011-12-05
6 2 4 2011-12-06
7 3 1 2011-12-07
8 3 2 2011-12-08
9 3 3 2011-12-09
The query would return row 9. (It has the highest Cycle_Day within the highest Cycle_Number)
Thanks
this one is compatible MySql 5.5 with no joint tables
SELECT id
FROM cycles
ORDER BY Cycle_Number DESC , Cycle_Day DESC
LIMIT 0 , 1
Regards
This SQL query should provide the max value you want.
SELECT ID, Cycle_Number, Cycle_Day, Date
FROM yourTable AS t
CROSS JOIN (
SELECT MAX(Cycle_Number) AS Cycle_Number FROM yourTable
) AS sq USING (Cycle_Number)
ORDER BY Cycle_Day DESC LIMIT 1