Hi I have a mysql table and it contained something like this
HISTORY
===================
2013-07-01 16:23:43
2013-07-01 17:32:11
2013-07-01 20:44:22
2013-07-02 23:65:12
2013-07-03 10:23:32
2013:07-03 12:54:02
and etc........
for example the first three row are 2013-07-01 16:23:43, 2013-07-01 17:32:11, and
2013-07-01 20:44:22 and the lastest date in this history is 2013-07-01 20:44:22
So what I really want is.. Is there any way that I could make a selection that have a result like this
HISTORY
===================
2013-07-01 20:44:22
2013-07-02 23:65:12
2013:07-03 12:54:02
etc....
Thank You
Try this query
select date(history) as dat,
max(history)
from table1
group by dat
SQL FIDDLE
| DAT | MAX(HISTORY) |
-------------------------------------------------------------
| July, 01 2013 00:00:00+0000 | July, 01 2013 20:44:22+0000 |
| July, 02 2013 00:00:00+0000 | July, 02 2013 23:59:12+0000 |
| July, 03 2013 00:00:00+0000 | July, 03 2013 12:54:02+0000 |
Maybe it can be like that;
select Max(history) as MyMaxTimeForADay from MyTime t1 group by Date(t1.history);
you can see how is work at this link : http://sqlfiddle.com/#!2/12be2/2/0
Related
I have a data set of projects. The projects change status from beginning to end, and the date of the status change is logged in a table (table is named "events" - not my choice). Would look like this (simplified):
Date Status
2015-06-01 Start
2015-06-03 Stage 2
2015-06-07 Stage 3
In any given date range (to be determined dynamically) I want to be able to see which projects are at which status. However, using BETWEEN or other query against the data will only pull those projects whose status changed during that period, not the ones that are still at a given status.
I've currently created a very clunky solution in Excel which copies rows into new rows between status change dates, like so:
Date Status
2015-06-01 Project start
2015-06-02 Project start (copied)
2015-06-03 Stage 2
2015-06-04 Stage 2 (copied)
2015-06-05 Stage 2 (copied)
2015-06-06 Stage 2 (copied)
2015-06-07 Stage 3
This solution allows me to query the status for the project on, say, 2015-06-06 and see that it is still at Stage 2.
Is there some way I can use mySql to pull this same data, but as output to a query? I've heard some suggest to use a Calendar table, but I'm not sure how that would work. I've also seen someone recommend a Cross Join, but again, I couldn't understand from the description how that would work.
Thanks in advance for your help!
plan
create calendar table by cross joining digits and date_add over calendar period..
join your data to calendar source with date <= calendar date
take max of date <= calendar date
join back to original data source to get status
setup
drop table if exists calendar_t;
CREATE TABLE calendar_t (
id integer primary key auto_increment not null,
`date` date not null,
day varchar(9) not null,
month varchar(13) not null,
`year` integer not null
);
drop view if exists digits_v;
create view digits_v
as
select 0 as n
union all
select 1
union all
select 2
union all
select 3
union all
select 4
union all
select 5
union all
select 6
union all
select 7
union all
select 8
union all
select 9
;
insert into calendar_t
( `date`, day, month, `year` )
select
date_add('2015-01-01', interval 100*a2.n + 10*a1.n + a0.n day) as `date`,
dayname(date_add('2015-01-01', interval 100*a2.n + 10*a1.n + a0.n day)) as day,
monthname(date_add('2015-01-01', interval 100*a2.n + 10*a1.n + a0.n day)) as month,
year(date_add('2015-01-01', interval 100*a2.n + 10*a1.n + a0.n day)) as `year`
from
digits_v a2
cross join digits_v a1
cross join digits_v a0
order by date_add('2015-01-01', interval 100*a2.n + 10*a1.n + a0.n day)
;
drop table if exists example;
create table example
(
`date` date not null,
status varchar(23) not null
);
insert into example
( `date`, status )
values
( '2015-06-01', 'Start' ),
( '2015-06-03', 'Stage 2' ),
( '2015-06-07', 'Stage 3' )
;
query
select cal_date, mdate, ex2.status
from
(
select cal_date, max(ex_date) as mdate
from
(
select cal.`date` as cal_date, ex.`date` as ex_date
from calendar_t cal
inner join example ex
on ex.`date` <= cal.`date`
) maxs
group by cal_date
) m2
inner join example ex2
on m2.mdate = ex2.`date`
-- pick a reasonable end date for filtering..
where cal_date <= date('2015-06-15')
order by cal_date
;
output
+------------------------+------------------------+---------+
| cal_date | mdate | status |
+------------------------+------------------------+---------+
| June, 01 2015 00:00:00 | June, 01 2015 00:00:00 | Start |
| June, 02 2015 00:00:00 | June, 01 2015 00:00:00 | Start |
| June, 03 2015 00:00:00 | June, 03 2015 00:00:00 | Stage 2 |
| June, 04 2015 00:00:00 | June, 03 2015 00:00:00 | Stage 2 |
| June, 05 2015 00:00:00 | June, 03 2015 00:00:00 | Stage 2 |
| June, 06 2015 00:00:00 | June, 03 2015 00:00:00 | Stage 2 |
| June, 07 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 |
| June, 08 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 |
| June, 09 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 |
| June, 10 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 |
| June, 11 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 |
| June, 12 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 |
| June, 13 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 |
| June, 14 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 |
| June, 15 2015 00:00:00 | June, 07 2015 00:00:00 | Stage 3 |
+------------------------+------------------------+---------+
sqlfiddle
reference
SO mysql sequence generation
sql cross join
you dont need to create a table with all the dates. you could alter your table to give the start and end dates for each status and use a between statement.
or using your existing data.
using #datequery as the date you want to find out the status for.
Select top 1 Status from Events
where Date <= #datequery and Date
order by Date desc
returns the most recent status change before the date you are querying.
#datequery = 2015-06-06
Status
Stage 2
Here is what my table looks like
----------------------------+-----------+
| tw_dt | text | ID |
+--------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+-----------+
| Thu Dec 12 19:14:13 +0000 2013 | #CoSignCountdown airs MON-FRI #7p send in your hottest song to cosigncountdown#gmail.com Original music ONLY!!! #TEAMFOLLOWBACK #HipHopDotCA | 14985388 |
| Thu Dec 12 19:14:12 +0000 2013 | "Get any Beat at http://t.co/R61XJ5EYUQ for $200 each. Exclusive Rights. To pruchase - GummyBeatz#Gmail.com" | 170900539 |
| Thu Dec 12 19:14:09 +0000 2013 | "#iwantmixedbabys PREMO is looking for Models for the SuperBadd fashionshow January10th 3000 EXPECTED email us premopresents#gmail.com" | 343062689 |
| Thu Dec 12 19:14:09 +0000 2013 | mixtape hosting contact . bookdjlyrical#gmail.com | 99644471 |
| Thu Dec 12 19:14:09 +0000 2013 | checkout http://t.co/4f2txyVpLy RIGHT NOW!!!! #Artist send in music and videos to preciseearz#gmail.com #BlogsAreTheNewMixtapes | 27872863 |
| Thu Dec 12 20:01:10 +0000 2013 | ATTENTION ARTISTS: DO YOU NEED US TO HELP YOU PROMOTE YOUR MUSIC?!? EMAIL US FOR OUR PROMO PACKAGES AT VIEWHIPHOP#gmail.com | 357913081 |
| Thu Dec 12 20:01:10 +0000 2013 | RT #ITSMIKESWAGGER: #Mike_Bell1 no doubt my artist appreciates the love mikeswagger#gmail.com hit me up | 165499064 |
| Thu Dec 12 20:01:10 +0000 2013 | #grandst #cmj_333 - swking1964#gmail.com is my Santa - but just needs to be aware of your site in General! Happy Holidays! | 574317429 |
+--------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+-----------+
I want to extract the email address from the text as it's own column.
Any thoughts on how I accomplish this in MYSQL?
Well, there's this huge regex for matching e-mail addresses. Combined with the regex replace solution found here, you should be good to go.
I was given a job to create a new table in the database with correct data type. Here are sample records:
RegisteredMonthYear
------------------------
May 2011
March 1998
January 2000
Before I will insert the converted value I tried to convert it using STR_TO_DATE() to check if the values are correct and the result were exactly not I want. This is my query:
SELECT RegisteredMonthYear,
STR_TO_DATE(RegisteredMonthYear, '%M %Y') NewDate,
STR_TO_DATE(CONCAT(RegisteredMonthYear, ' 01'), '%M %Y %d') newDate2,
STR_TO_DATE(RegisteredMonthYear, '%M %Y') + INTERVAL 1 DAY newDate3
FROM TableName
+---------------------+---------------------------------+--------------------------------+----------+
| REGISTEREDMONTHYEAR | NEWDATE | NEWDATE2 | NEWDATE3 |
+---------------------+---------------------------------+--------------------------------+----------+
| May 2011 | April, 30 2011 00:00:00+0000 | May, 01 2011 00:00:00+0000 | (null) |
| March 1998 | February, 28 1998 00:00:00+0000 | March, 01 1998 00:00:00+0000 | (null) |
| January 2000 | December, 31 1999 00:00:00+0000 | January, 01 2000 00:00:00+0000 | (null) |
+---------------------+---------------------------------+--------------------------------+----------+
see here for demo: http://www.sqlfiddle.com/#!2/89a67/7
As you can see, column NEWDATE is one day behind. Why are the result like this?
When I tried to concatenate 01 in the string in column NEWDATE2 the result is as expected. Going back on NEWDATE column, I tried to add one day thinking that it will give exact value in column NEWDATE3 but the result is NULL.
Any idea about this?
You can use following formula (SQLFiddle):
SELECT date(str_to_date(RegisteredMonthYear, '%M %Y'))
+ interval 1 day
FROM tablename
I have added extra DATE() call on top of STR_TO_DATE() - but it makes all the difference.
But in general I agree that this is one more really weird MySQL gotcha.
For example, in PostgreSQL, you don't need to add 1 day and you don't need extra casts, simple to_timestamp is enough:
SELECT to_timestamp('May 2011', 'Mon YYYY');
2013-05-01 00:00:00-07
I have to find the difference in the value of a single column of table as current row value-previous row value for some 'n' number of rows in one column and also I don't have ID to use as reference for increment
date: box_count : total_no_of_boxes_used
1/12/12 2 2
2/12/12 8 6
3/12/12 14 6
I have box_count column and I am trying to get total_no_of_boxes_used column.
Please help me.
Thanks in advance
Given your records are sequential by date.....
SQLFIDDLE DEMO
Query:
select a.date, a.bc, case when (a.bc-b.bc) is null then a.bc else a.bc-b.bc end tot
from tt a
left join
tt b
on a.date > b.date
group by b.date
;
Results:
DATE BC TOT
December, 01 2012 00:00:00+0000 2 2
December, 02 2012 00:00:00+0000 8 6
December, 03 2012 00:00:00+0000 14 6
December, 04 2012 00:00:00+0000 23 9
One way to do this, is using a correlated subquery like so:
SELECT
t1.`date`,
t1.box_count,
t1.box_count -
IFNULL((SELECT t2.box_count
FROM table1 t2
WHERE t2.`date` < t1.`date`
ORDER BY t2.`date` DESC
LIMIT 1),
0 ) AS total_no_of_boxes_used
FROM table1 t1;
SQL Fiddle Demo
This will give you:
| DATE | BOX_COUNT | TOTAL_NO_OF_BOXES_USED |
------------------------------------------------------------------------
| January, 12 2012 00:00:00+0000 | 2 | 2 |
| February, 12 2012 00:00:00+0000 | 8 | 6 |
| March, 12 2012 00:00:00+0000 | 14 | 6 |
Try this:
SELECT date,
(box_count - #diff) total_no_of_boxes_used,
(#diff:=box_count) box_count
FROM table1, (SELECT #diff:=0) A;
Check this SQL FIDDLE DEMO
OUTPUT
| DATE | TOTAL_NO_OF_BOXES_USED | BOX_COUNT |
------------------------------------------------------------------------
| January, 12 2012 00:00:00+0000 | 2 | 2 |
| February, 12 2012 00:00:00+0000 | 6 | 8 |
| March, 12 2012 00:00:00+0000 | 6 | 14 |
I currently have a table where I record all my employee daily expenses
John Smith 01 JAN 2010 200$
John Smith 01 JAN 2010 50$
John Smith 01 JAN 2010 10$
Lady Gaga 01 JAN 2010 50$
Lady Gaga 01 JAN 2010 20$
John Smith 02 JAN 2010 10$
What I would like to display a table that contains a daily report of all bills:
01 JAN 2010
John Smith: 260$
Lady Gaga: 70$
02 JAN 2010
John Smith: 10$
I really hope my request is understandable and you will be able to help me.
Thank a lot for any advice!
I would use a standard group-by:
select date, name, sum(amount) as total
from mytable
group by 1,2
order by 1,2;
use SUM with GROUP BY , do something like
SELECT date,user,SUM(cost)
FROM mytable
GROUP BY date,user
ORDER BY date