Get min and max time from date from multiple rows - mysql

I have this table with following data.
Uid date time
1 2019-07-17 09:00:09
1 2019-07-17 17:30:32
1 2019-07-18 09:30:00
1 2019-07-19 09:14:23
1 2019-07-19 13:14;56
1 2019-07-19 17:34:22
I want to get these into following
1 2019-07-17 09:00:09 17:30:32
1 2019-07-18 09:30:00
1 2019-07-19 09:14:23 17:34:22
I am not good at SQL, so looking for the community help. Thank you

This is basically aggregation. A handy way to do this uses nullif():
select uid, date, min(time), nullif(max(time), min(time))
from t
group by uid, date

You can do this by grouping first by id and then date to get all unique records. Then you retrieve the min and max time values in the select statement.
SELECT uid, date, min(time), max(time)
FROM your_table
GROUP BY uid, date

you could use min() max() and group by check for min() and max() not equal
select uid, date, min(time) min_time
, case when min(time) = max(time) then null else max(time) end max_time
from my_table
group by uid, date

Related

Get Minimum date for all users in mysql

how to get the minimum created date per user_id? sql_mode=only_full_group_by is enabled
SELECT
user_id,
min(created_at)
FROM
subscribers
GROUP BY
created_at,
user_id
GROUP BY
user_id,
created_at
HAVING
MIN(DATE_FORMAT(created_at, '%Y-%m-%d')) > '2022-10-01'
Data is like this
user_id
created_at
12
2022-11-11 12:10:11
13
2021-10-11 12:10:11
12
2022-08-11 11:10:11
15
2022-08-11 11:10:11
Expected result
user_id
13
12
Just use GROUP BY for grouping your users and then use MIN to find the minimum date;
SELECT
d.`user_id`,
MIN(d.`created_at`)
FROM
subscribers d
GROUP BY d.`user_id`
If you want it in more sophisticated way, use:
SELECT
* ,
(SELECT MIN(d1.created_at) FROM subscribers d1 WHERE d1.user_id=a.userId ) AS createdAt
FROM
(SELECT
DISTINCT d.`user_id` AS userId
FROM
subscribers d) a

how to find the first and last records of every month in mysql database

I want to fetch the first and last record of every month in sql but my query give the results below and here is my query
SELECT DISTINCT month, amount,
MIN(date) OVER (PARTITION BY month ORDER BY utility.month)
FROM
utility;
results of the query above
month
amount
min(date)
February/2022
200
2022-02-02
January/2022
1000
2022-01-01
January/2022
200
2022-01-01
March/2022
1000
2022-02-06
You can get the MIN() and MAX() value first, turn into a subquery then join utility table twice to get the amount corresponding to the extracted dates, like this:
SELECT v.month,
v.mindt,
u1.amount,
v.maxdt,
u2.amount
FROM
(SELECT month,
MIN(date) mindt, MAX(date) maxdt
FROM
utility
GROUP BY month) v
JOIN utility u1 ON u1.date=v.mindt
JOIN utility u2 ON u2.date=v.maxdt
;
That will give result something like this:
month
mindt
amount
maxdt
amount
January2022
2022-01-02
250
2022-01-29
350
February2022
2022-02-01
300
2022-02-28
500
March2022
2022-03-03
500
2022-03-18
300
Or you can modify the subquery to do UNION ALL, join utility once and return all in just the original 3 columns:
SELECT v.month,
v.minmaxdt,
u.amount
FROM
(SELECT month,
MIN(date) minmaxdt
FROM utility
GROUP BY month
UNION ALL
SELECT month,
MAX(date)
FROM utility
GROUP BY month
) v
JOIN utility u ON u.date=v.minmaxdt
ORDER BY v.month, v.minmaxdt;
That will give result something like this:
month
minmaxdt
amount
February2022
2022-02-01
300
February2022
2022-02-28
500
January2022
2022-01-02
250
January2022
2022-01-29
350
March2022
2022-03-03
500
March2022
2022-03-18
300
Demo fiddle
Try using MIN and MAX at the same time together with GROUP BY.
Check this from W3Schools.
The MIN() function returns the smallest value of the selected column.
The MAX() function returns the largest value of the selected column.
Try this code:
SELECT DISTINCT month, amount, MIN(date), MAX(date) FROM utility GROUP BY month;

Count distinct per month/year but display all dates in the query result

DB-Fiddle
CREATE TABLE sales (
id int auto_increment primary key,
orderID VARCHAR(255),
sent_date DATE
);
INSERT INTO sales
(orderID, sent_date
)
VALUES
("Order_01", "2019-03-15"),
("Order_01", "2019-03-16"),
("Order_02", "2020-06-16"),
("Order_03", "2020-07-27"),
("Order_03", "2020-08-05"),
("Order_03", "2020-08-10");
Expected Result:
sent_date COUNT(distinct orderID)
2019-03-15 1
2019-03-16 0
2020-06-16 1
2020-07-27 1
2020-08-05 1
2020-08-10 0
In the above table I have the same orders with multiple sent_dates.
Now, I want to count the unique orderIDs per month/year on a daily-basis.
Therefore, I am looking for a query that checks for each orderID if it already exists at a previous sent_date and if so the value for the current sent_date should be 0.
I know the most simple way to the unique count per month/year would be this query:
SELECT
YEAR(sent_date),
MONTH(sent_date),
COUNT(distinct orderID)
FROM sales
GROUP BY 1,2;
However, I need to have each sent_date displayed seperately in a list as you can see in the expected result.
What query do I need to get the count unique although I need to query the data on a daily-basis?
If I understand correctly, you want to flag the first occurrence of each order in a month. You can use window functions:
select s.*,
( row_number() over (partition by extract(year_month from sent_date), orderid order by sent_date) = 1 ) as flag
from s;
Window functions are supported in MySQL 8+.
I think that you want to a histogram of the first monthly occurence of each orderid per date.
Here is an approach using window functions, available in MySQL 8.0:
select sent_date, sum(rn = 1) cnt_distinct_orderid
from (
select s.*, row_number() over(partition by year(sent_date), month(sent_date), orderid order by sent_date) rn
from sales s
) t
group by sent_date
order by sent_date
In earlier versions, one option uses a self-join:
select d.sent_date, count(s.orderid) cnt_distinct_orderid
from (select distinct sent_date from sales) d
left join (
select orderid, min(sent_date) min_sent_date
from sales
group by orderid, date_format(sent_date, '%Y-%m-01')
) s on d.sent_date = s.min_sent_date
group by d.sent_date
Demon on DB Fiddle:
sent_date | cnt_distinct_orderid
:--------- | -------------------:
2019-03-15 | 1
2019-03-16 | 0
2020-06-16 | 1
2020-07-27 | 1
2020-08-05 | 1
2020-08-10 | 0

Mysql : Selecting a monthly total occurence count

In MySQL, I got a table similar to :
id user_id date
1 1 2014-09-27
2 1 2014-11-05
3 1 2014-11-14
4 2 2014-12-03
5 1 2014-12-23
I would like to select the total monthly amount of people.
ExpectedOutput : 4
2014-09 = 1 user
2014-10 = 0 user
2014-11 = 1 user //user 1 is present twice in november, but I want him only once per month
2014-12 = 2 user
total expected = 4
So far, my request is :
SELECT count(id)
FROM myTable u1
WHERE EXISTS(
SELECT id
FROM myTable u2
WHERE u2.user_id = u1.user_id
AND DATE_SUB(u2.date, INTERVAL 1 MONTH) > u1.date
);
It ouput the correct amount, but on my (not so heavy) table, it take hours to execute. Any hints to make this one lighter or faster ?
Bonus :
Since INTERVAL 1 MONTH is not available in DQL, is there any way to do it with a Doctrine QueryBuilder ?
Try this!
It should give you exactly what you need...
SELECT
EXTRACT(YEAR FROM dates) AS the_year,
EXTRACT(MONTH FROM dates) AS the_month,
COUNT( DISTINCT user_id ) AS total
FROM
myTable
GROUP BY
EXTRACT(YEAR FROM dates),
EXTRACT(MONTH FROM dates);
For you problem, what I would do is :
Creating a subrequst grouping the distinct sum of people by month
Creating a request making the sum of the sub-result.
Here is a working example (with your datas) sqlFiddle
And here is the request :
SELECT SUM(nb_people)
FROM (
-- This request return the number of distinct people in one month.
SELECT count(distinct(user_id)) AS nb_people, MONTH(`date`), YEAR(`date`)
FROM test
GROUP BY MONTH(`date`)
) AS subQuery
;
SELECT COUNT(DISTINCT user_id), YEAR(date) + '-' + MONTH(date)
FROM MyTable
GROUP BY YEAR(date), MONTH(date)

sort by date with sum clause

I have this table:
-----------------------------------------------------------
| id | name | date | count | balance |
-----------------------------------------------------------
1 a 0000-00-00 1 10
2 b 2014-10-02 1 20
3 c 2014-09-01 1 30
4 d 2014-09-16 1 40
I need to get the SUM of the four count & balance column on my SELECT, then order it by the date in ascending but I need to make sure it should not be the 0000-00-00. I tried this syntax but it does not order the date the way I wanted.
SELECT
date,
SUM(count) AS deposit_counts,
SUM(balance) AS balance_sum
FROM tbl
ORDER BY date ASC
My expected output:
-------------------------------------------
| date | count | balance |
-------------------------------------------
2014-09-01 4 90
Use MIN and NULLIF functions:
SELECT
MIN(NULLIF(date, '0000-00-00')) AS min_date,
SUM(count) AS deposit_counts,
SUM(balance) AS balance_sum
FROM tbl
Test it here: http://sqlfiddle.com/#!2/d43acf/1
I wish I understood the point in having a 0000-00-00 date as opposed to having null so only one possibility needs ruling out... Anyway at first I would assume you might want to get the total balances of each day and would require a query along these lines
SELECT
date,
sum(count) AS deposit_counts,
SUM(balance) AS balance_sum
FROM tbl
WHERE date <> '0000-00-00'
GROUP BY date
ORDER BY date
which would output
2014-09-01 1 30
2014-09-16 1 40
2014-10-02 1 20
but as it stands it appears you don't, I'm not one hundred percent sure what your ultimate goal is in terms of future querying so I will guess you want a historical value of balances up to the current date, ruling out the weird zero date thing. In which case you might want a greater than WHERE clause, and presumably just the lowest value in the date column to show the total from this date like so:
SELECT
min(date) AS date,
sum(count) AS deposit_counts,
SUM(balance) AS balance_sum
FROM tbl
WHERE date > '0000-00-00'
since it would ignore the invalid date it will return
2014-09-01 3 80
I hope this is of some use.
Edit:
if you absolutely require all values then you will want to use a subquery to retrieve and rule out the exceptional date result like so:
SELECT
(SELECT min(date) FROM tbl WHERE date > '0000-00-00') AS date,
sum(count) AS deposit_counts,
SUM(balance) AS balance_sum
FROM tbl
or as above, nullif on your date query should work too