I have two tables:
Table 1: planA
ID Date Count
3 2017-01-01 10
2 2017-02-03 15
10 2017-01-30 8
Table 2: planB
ID Date Value
3 2017-01-02 11
2 2017-02-04 12
21 2017-01-30 3
3 2017-02-03 33
What I want to do is to join the two tables on (ID and Date) columns.
However, on Date, I want to use the next day to the date on the table 1.
Therefore, the joined table should look like the following:
PlanA.ID PlanA.Date PlanB.Date PlanA.Count PlanB.Value
3 2017-01-01 2017-01-02 10 11
2 2017-02-03 2017-02-04 15 12
Is this even possible?
Any suggestion would be appreciated!
Yes it is possible:
select
PlanA.ID,
PlanA.Date,
PlanB.Date,
PlanA.Count,
PlanB.Value
from
PlanA inner join PlanB
on (
PlanA.ID = PlanB.ID
and
PlanA.Date + INTERVAL 1 DAY = PlanB.Date
)
if Date is a column of type date, + INTERVAL 1 DAY will return the next day of the one given, and then you can perform the join.
Related
EDIT: I have added the primary key, following the comment by #Strawberry
The aim is to return the number of current members, and also the number of past memberships, on any particular date/time.
For example, suppose we have
msid id start cancelled
1 1 2020-01-01 09:00:00 null
2 2 2020-01-01 09:00:00 2020-12-31 09:00:00
3 2 2021-01-01 09:00:00 null
4 3 2020-01-01 09:00:00 2020-06-30 09:00:00
5 3 2020-02-01 09:00:00 2020-06-30 09:00:00
6 3 2020-07-01 09:00:00 null
and we want to calculate the number of members at various times, which should return as follows
Datetime Current Past <Notes - not to be returned by the query>
2020-01-01 12:00:00 3 0 -- all 3 IDs have joined earlier on this date
2020-02-01 12:00:00 3 0 -- new membership for existing member (ID 3) is not counted
2020-06-30 12:00:00 2 1 -- ID 3 has cancelled earlier on this day
2020-07-01 12:00:00 3 0 -- ID 3 has re-joined earlier on this day
2020-12-31 12:00:00 2 1 -- ID 2 has cancelled earlier on this day
2021-01-01 12:00:00 3 0 -- ID 2 has re-joined earlier on this day
An ID may either be current or past, but never both. That is, if a past member re-joins, as in the case of ID 2 and 3 above, they become current members, and are no longer past members.
Also, a member may have multiple current memberships, but they can only be counted as a current member once, as in the case of ID 3 above.
How can this be achieved in MySQL ?
Here is a db<>fiddle with the above data
Test this:
WITH
cte1 AS ( SELECT start `timestamp` FROM dt
UNION
SELECT cancelled FROM dt WHERE cancelled IS NOT NULL ),
cte2 AS ( SELECT DISTINCT id
FROM dt )
SELECT cte1.`timestamp`, COUNT(DISTINCT dt.id) current, SUM(dt.id IS NULL) past
FROM cte1
CROSS JOIN cte2
LEFT JOIN dt ON cte1.`timestamp` >= dt.start
AND (cte1.`timestamp` < dt.cancelled OR dt.cancelled IS NULL)
AND cte2.id = dt.id
GROUP BY cte1.`timestamp`
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=942e4c97951ed0929e178134ef67ce69
I am using MySQL, I have following table structure
Id id2 classId sectionId validFrom validTill
------------------------------------------------------
1 1 5 13 2016-01-01 2016-03-30
2 1 5 22 2016-01-15 2016-03-30
3 1 5 23 2016-01-15 2016-04-29
4 1 5 13 2016-04-01 2016-04-30
9 10 6 24 2016-01-17 2016-02-05
10 10 6 25 2016-01-23 2016-02-05
11 10 6 24 2016-01-31 2016-02-05
My SQL statement is
SELECT count(*) as timeCount FROM TimeTableClassSection a
WHERE classId=5 AND sectionId=13 AND ((a.ValidFrom BETWEEN '2016-01-18' AND '2016-01-24') OR (a.ValidTill BETWEEN '2016-01-18' AND '2016-01-24'))
Its returning timeCount = 0. But it should return 1 as record with Id=1 falls between this date range ('2016-01-18' AND '2016-01-24')
I am trying to achieve, find out any overlapping record for particular classId & sectionId between provided date range.
If classId=5 and sectionId=13 has validFrom=2016-01-01 validTill=2016-03-30 exist, then any date range between this date range ('2016-01-18' AND '2016-01-24') should throw this record as count.
If I give date range 2015-12-25 to 2016-09-20 then record count should = 1
If I give date range 2016-2-1 to 2016-02-20 then record count should = 1
If I give date range 2016-2-1 to 2016-09-20 then record count should = 1
What wrong I am doing here ... all date format is in YYYY-MM-DD
You are only checking if the boundaries are within the date range, but you do not check whether the data range is within the boundaries. You should extend your where criteria:
...AND ((a.ValidFrom BETWEEN '2016-01-18' AND '2016-01-24')
OR (a.ValidTill BETWEEN '2016-01-18' AND '2016-01-24')
OR (a.ValidFrom<'2016-01-18' AND a.ValidTill>'2016-01-24'))
There's a DATETIME column called time. How could I select all rows that fall within the last existing 12 months (NOT within the last year from today)? Not every month might have a row, and months may have more than one row.
For example, out of this table (ORDER BY time DESC), rows with ids 2 to 17 would be selected.
id time
-- ----
17 2015-04-01
16 2015-04-01
15 2015-03-01
14 2015-02-01
13 2015-01-01
12 2014-12-01
11 2014-11-01
10 2014-10-01
9 2013-12-01
8 2013-11-01
7 2013-10-01
6 2013-09-01
5 2013-09-01
4 2013-09-01
3 2013-09-01
2 2013-08-01
1 2013-07-01
Another way to put this:
Take the table above and group by month/year, so we get:
2015-04
2015-03
2015-02
2015-01
2014-12
2014-11
2014-10
2013-12
2013-11
2013-10
2013-09
2013-08
2013-07
Now take the 12 most recent months from this list, which is everything except 2013-07.
2015-04
2015-03
2015-02
2015-01
2014-12
2014-11
2014-10
2013-12
2013-11
2013-10
2013-09
2013-08
And select everything from those months.
I guess I could do this with multiple queries or subqueries but is there another way to do this?
If your time field is only month-precision, you could do it with a pretty simple subselect:
SELECT * FROM Table t1
WHERE time IN (
SELECT DISTINCT time FROM Table t2 ORDER BY time DESC LIMIT 12
)
If your timestamps are full-precision, you could do the same thing, but you'd need to do some date manipulation to round the dates to the month for comparison.
I have the following table:
id | start_date | end_date | client_id
1 2013-08-01 2013-08-09 1
2 2013-08-10 2013-08-10 1
3 2013-08-10 2013-08-17 1
4 2013-08-18 2013-08-18 1
5 2013-08-18 2013-08-18 1
6 2013-08-18 2013-08-31 1
7 2013-08-01 2013-08-09 2
8 2013-08-11 2013-08-11 2
9 2013-08-11 2013-08-17 2
10 2013-08-19 2013-08-20 2
what I'm trying to do is count the number of days that each client was present without repeating the days for each client, so from the previous data I'm looking to get:
client_id | total_days
1 31
2 18
So for client 1 I get 31 because he was "present" for 31 days, from 8/1/2013 - 8/31/2013 with no gaps, and for client 2 I get 18 because he was present for 18 days:
8/1 - 8/9 = 9 days
8/11 - 8/17 = 7 days
8/19 - 8/20 = 2 days
is there anyway to achieve this in MySQL, I've been trying for a while but have no idea on how to do it.
This is the fiddle
If overlapping ranges exist, then I suggest building a driver table that is a list of dates, then JOIN to that table using BETWEEN:
SELECT a.Client_ID, COUNT(DISTINCT b.Date)
FROM YourTable a
JOIN Dates b
ON b.Date BETWEEN a.start_date AND a.end_date
GROUP BY a.Client_ID
Demo: SQL Fiddle
There are plenty of places to find calendar table logic, here's one.
If ranges never overlap then you can use SUM(DATEDIFF()).
If there are no overlapping ranges. You can use the following query:
SELECT Client_id,
Sum(DATEDIFF(End_date, Start_date)) AS `Present`
FROM TABLE
GROUP BY Client_id;
This will give you an overview of the number of days a client was present.
I have Table with 3 Columns, Column1 with Date and Column2 stores Points which is nothing but Some random Number between 1 to 9 and column 3 which have some unique email address in every cell.
Now I want to add the points grouped by date for last 5 days.
That is if I have 3 rows for day one, 1 rows for day two, 3 rows for day 3 and 2 rows for day 4 & 5 I should get the sum of points of these 11 rows grouped by date as 5 rows for five days.
Input
Date Points
Email
2012-07-01 5 a#sample.com
2012-07-01 6 b#sample.com
2012-07-01 2 c#sample.com
2012-07-02 5 d#sample.com
2012-07-03 8 e#sample.com
2012-07-03 7
f#sample.com
2012-07-03 1
y#sample.com
2012-07-04 3 x#sample.com
2012-07-04 2 f#sample.com
2012-07-05 3 g#sample.com
2012-07-05 9 b#sample.com
Output
Date Points
2012-07-01 13
2012-07-02 5
2012-07-03 16
2012-07-04 5
2012-07-05 12
Please suggest me a MySQL query for the above.
select `Date`,sum(`Points`) from my_table group by `Date`;
select `Date`,sum(`Points`) from my_table group by `Date` Limit 5;
select Date,sum(Points) from my_table group by Date;
select [Date],SUM(Points)
from myTable1
group by [Date]
You can do:
SELECT date, SUM(points) AS points
FROM tbl
WHERE date > CURDATE() - INTERVAL 5 DAY
GROUP BY date