I have a mysql table with date column. date column data type is TIMESTAMP and default set to CURRENT_TIMESTAMP which record both date and time
now i want to count my rows under given day
As an example
++++++++++ 8am 9am 10am 11am
++user1+++ 15 10 11 10
++user2+++ 10 10 20 30
Every hour count should be recorded separately like this.
i tried with this but it's not working
SELECT COUNT(*) FROM mytable
WHERE `date` = '2015-01-26'
GROUP BY HOUR(`TIMESTAMP`)
how can i achieve this ?
i have no idea how to group with user . sproc is also okay
I made a sproc like this. but this sproc contain errors. can some one please help me now i want to count this separated by 9 hours
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `test22`(IN datestamp DATE)
BEGIN
SELECT username,
COUNT(if(disblid,1,null)) '8:00 AM', where time between '08:00' and '09:00':
COUNT(if(disblid,1,null)) '9:00 AM' , where time between '09:00' and '10:00';
FROM claimloans
WHERE DATE(date) = datestamp
group by Username;
END
Thanks for everyone who helped me I come up with sproc that working perfectly fine.
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `claimscounter`(IN datestamp DATE)
BEGIN
SELECT username,
COUNT(IF(HOUR(date)=0,1,NULL)) AS '12am',
COUNT(IF(HOUR(date)=1,1,NULL)) AS '1am',
COUNT(IF(HOUR(date)=2,1,NULL)) AS '2am',
COUNT(IF(HOUR(date)=3,1,NULL)) AS '3am',
COUNT(IF(HOUR(date)=4,1,NULL)) AS '4am',
COUNT(IF(HOUR(date)=5,1,NULL)) AS '5am',
COUNT(IF(HOUR(date)=6,1,NULL)) AS '6am',
COUNT(IF(HOUR(date)=7,1,NULL)) AS '7am',
COUNT(IF(HOUR(date)=8,1,NULL)) AS '8am',
COUNT(IF(HOUR(date)=9,1,NULL)) AS '9am',
COUNT(IF(HOUR(date)=10,1,NULL)) AS '10am',
COUNT(IF(HOUR(date)=11,1,NULL)) AS '11am',
COUNT(IF(HOUR(date)=12,1,NULL)) AS '12pm',
COUNT(IF(HOUR(date)=13,1,NULL)) AS '1pm',
COUNT(IF(HOUR(date)=14,1,NULL)) AS '2pm',
COUNT(IF(HOUR(date)=15,1,NULL)) AS '3pm',
COUNT(IF(HOUR(date)=16,1,NULL)) AS '4pm',
COUNT(IF(HOUR(date)=17,1,NULL)) AS '5pm',
COUNT(IF(HOUR(date)=18,1,NULL)) AS '6pm',
COUNT(IF(HOUR(date)=19,1,NULL)) AS '7pm',
COUNT(IF(HOUR(date)=20,1,NULL)) AS '8pm',
COUNT(IF(HOUR(date)=21,1,NULL)) AS '9pm',
COUNT(IF(HOUR(date)=22,1,NULL)) AS '10pm',
COUNT(IF(HOUR(date)=23,1,NULL)) AS '11pm'
FROM claimloans
WHERE DATE(date) = datestamp
group by username;
END
But now I have another small problem. This count all the hours. if it's not entry for some hour it count as zero. I want to count hours only have records can someone help me with this
thnaks
I would solve this as a view, like so:
CREATE TABLE foo (id int not null, val timestamp);
CREATE VIEW foo_by_hours AS (
SELECT
id,
DATE(val) AS 'day',
COUNT(IF(HOUR(val)=0,1,NULL)) AS '12am',
COUNT(IF(HOUR(val)=1,1,NULL)) AS '1am',
COUNT(IF(HOUR(val)=2,1,NULL)) AS '2am',
COUNT(IF(HOUR(val)=3,1,NULL)) AS '3am',
...
FROM foo
GROUP BY id, day);
SELECT * FROM foo_by_hours;
Full example on SQL Fiddle
I also added a view which uses SUM instead of COUNT. The result is the same, it's just a different way of doing it.
Related
I want to average every hour data from 2 table (cuaca and data_monitoring) in MySQL then insert the result in another table (average) but my code doesn't work. If I just average from one table then insert the result in the another table, the code is working. I use scheduler because I need to know average result every hour
this ini my code, can you help me please?
DELIMITER $$
CREATE
EVENT `otomatis`
ON SCHEDULE EVERY 1 HOUR STARTS '2015-05-20 14:37:00'
DO BEGIN
truncate table average;
INSERT INTO `average`
(`tanggalave`, `avetemp`, `avehumid`,`avewind`)
SELECT `date` , avg(`suhu_udara`), avg(`kelembaban_udara`), avg(`kecepatan_angin`)
FROM `cuaca`
GROUP By DATE( date ), HOUR( date );
INSERT INTO `average`
(`avegel`)
SELECT avg(`tinggi_gelombang`)
FROM `data_monitoring`
GROUP By DATE( date ), HOUR( date );
END $$
DELIMITER ;
I need this query:
SELECT ItemID, Price
FROM table
WHERE ItemID = %d
GROUP BY Price
ORDER BY COUNT(*) DESC LIMIT 1
-run once a day, and have the results from it stored in another table with the time stamp of the query.
Is there a way I can automatically query all the available ItemID values? For example, if there are 20 ItemID values available, I need 20 separate queries.
You can use the mysql event scheduler for this. Here's an example with your current query inserting data into a table called "new_table", starting at 3 AM on March 28.
DELIMITER $$
CREATE
EVENT `daily_backup`
ON SCHEDULE EVERY 1 DAY STARTS '2015-03-28 03:00:00'
DO BEGIN
INSERT INTO new_table (ItemID, Price, Time)
SELECT ItemID, Price, NOW()
FROM table
WHERE ItemID = %d
GROUP BY Price
ORDER BY COUNT(*) DESC LIMIT 1;
END */$$
You can do the same thing with your other queries; they can be put into the same event, before the END
I am using SQL Server 2008 R2 and trying to find total records inserted between a range of dates grouped by insertdate. Since my insertdate contains hour,min and sec, all the records are being counted individually with same date but different time.
I want to keep the time information in my database but only in the query, I want to group by date omitting time.
#Created Date TotalRegistration
2014-10-20 14:40:47.757 1
2014-10-20 12:27:27.923 1
2014-10-20 12:25:25.613 1
should be
#Created Date TotalRegistration
2014-10-20 3
This is what I tried. Any suggestion will be really appreciated.
Thank You
Select Insertdate, COUNT(Insertdate) as TotalDailyRegistration from Customer where Insertdate between '2014-10-01 00:00:00.001' and '2014-11-08 23:59:59.743' group by Insertdate
Update: Followed Lamak's suggestion and it worked out fine. Since the dates were not ordered correctly, I also added order by CONVERT(DATE,Insertdate) after group by and its perfect.
It should be better to just group by the date part of your column:
SELECT CONVERT(DATE,Insertdate) InsertDate,
COUNT(Insertdate) as TotalDailyRegistration
FROM Customer
WHERE Insertdate >= '20141001'
AND InsertDate < '20141002'
GROUP BY CONVERT(DATE,Insertdate)
Just try this:
create table #test( createdDate datetime,totalRegistration int)
insert into #test values('2014-10-20 14:40:47.757',1)
insert into #test values('2014-10-20 12:27:27.923',1)
insert into #test values(' 2014-10-20 12:25:25.613',1)
select *From test
Select convert(nvarchar(10),createdDate,103), sum(totalRegistration) as TotalDailyRegistration
I need some help with a mysql query. I've got db table that has data from Jan 1, 2011 thru April 30, 2011. There should be a record for each date. I need to find out whether any date is missing from the table.
So for example, let's say that Feb 2, 2011 has no data. How do I find that date?
I've got the dates stored in a column called reportdatetime. The dates are stored in the format: 2011-05-10 0:00:00, which is May 5, 2011 12:00:00 am.
Any suggestions?
This is a second answer, I'll post it separately.
SELECT DATE(r1.reportdate) + INTERVAL 1 DAY AS missing_date
FROM Reports r1
LEFT OUTER JOIN Reports r2 ON DATE(r1.reportdate) = DATE(r2.reportdate) - INTERVAL 1 DAY
WHERE r1.reportdate BETWEEN '2011-01-01' AND '2011-04-30' AND r2.reportdate IS NULL;
This is a self-join that reports a date such that no row exists with the date following.
This will find the first day in a gap, but if there are runs of multiple days missing it won't report all the dates in the gap.
CREATE TABLE Days (day DATE PRIMARY KEY);
Fill Days with all the days you're looking for.
mysql> INSERT INTO Days VALUES ('2011-01-01');
mysql> SET #offset := 1;
mysql> INSERT INTO Days SELECT day + INTERVAL #offset DAY FROM Days; SET #offset := #offset * 2;
Then up-arrow and repeat the INSERT as many times as needed. It doubles the number of rows each time, so you can get four month's worth of rows in seven INSERTs.
Do an exclusion join to find the dates for which there is no match in your reports table:
SELECT d.day FROM Days d
LEFT OUTER JOIN Reports r ON d.day = DATE(r.reportdatetime)
WHERE d.day BETWEEN '2011-01-01' AND '2011-04-30'
AND r.reportdatetime IS NULL;`
It could be done with a more complicated single query, but I'll show a pseudo code with temp table just for illustration:
Get all dates for which we have records:
CREATE TEMP TABLE AllUsedDates
SELECT DISTINCT reportdatetime
INTO AllUsedDates;
now add May 1st so we track 04-30
INSERT INTO AllUsedData ('2011-05-01')
If there's no "next day", we found a gap:
SELECT A.NEXT_DAY
FROM
(SELECT reportdatetime AS TODAY, DATEADD(reportdatetime, 1) AS NEXT_DAY FROM AllUsed Dates) AS A
WHERE
(A.NEXT_DATE NOT IN (SELECT reportdatetime FROM AllUsedDates)
AND
A.TODAY <> '2011-05-01') --exclude the last day
If you mean reportdatetime has the entry of "Feb 2, 2011" but other fields associated to that date are not present like below table snap
reportdate col1 col2
5/10/2011 abc xyz
2/2/2011
1/1/2011 bnv oda
then this query works fine
select reportdate from dtdiff where reportdate not in (select df1.reportdate from dtdiff df1, dtdiff df2 where df1.col1 = df2.col1)
Try this
SELECT DATE(t1.datefield) + INTERVAL 1 DAY AS missing_date FROM table t1 LEFT OUTER JOIN table t2 ON DATE(t1.datefield) = DATE(t2.datefield) - INTERVAL 1 DAY WHERE DATE(t1.datefield) BETWEEN '2020-01-01' AND '2020-01-31' AND DATE(t2.datefield) IS NULL;
If you want to get missing dates in a datetime field use this.
SELECT CAST(t1.datetime_field as DATE) + INTERVAL 1 DAY AS missing_date FROM table t1 LEFT OUTER JOIN table t2 ON CAST(t1.datetime_field as DATE) = CAST(t2.datetime_field as DATE) - INTERVAL 1 DAY WHERE CAST(t1.datetime_field as DATE) BETWEEN '2020-01-01' AND '2020-07-31' AND CAST(t2.datetime_field as DATE) IS NULL;
The solutions above seem to work, but they seem EXTREMELY slow (taking possibly hours, I waited for 30 min only) at least in my database.
This clause takes less than a second in same database (of course you need to repeat it manually dozen times and possibly change function names to find the actual dates). pvm = my datetime, WEATHER = my table.
mysql> select year(pvm) as _year,count(distinct(date(pvm))) as _days from WEATHER where year(pvm)>=2000 and month(pvm)=1 group by _year order by _year asc;
--ako
So lets say I have some records that look like:
2011-01-01 Cat
2011-01-02 Dog
2011-01-04 Horse
2011-01-06 Lion
How can I construct a query that will return 2011-01-03 and 2011-01-05, ie the unused dates. I postdate blogs into the future and I want a query that will show me the days I don't have anything posted yet. It would look from the current date to 2 weeks into the future.
Update:
I am not too excited about building a permanent table of dates. After thinking about it though it seems like the solution might be to make a small stored procedure that creates a temp table. Something like:
CREATE PROCEDURE MISSING_DATES()
BEGIN
CREATE TABLE TEMPORARY DATES (FUTURE DATETIME NULL)
INSERT INTO DATES (FUTURE) VALUES (CURDATE())
INSERT INTO DATES (FUTURE) VALUES (ADDDATE(CURDATE(), INTERVAL 1 DAY))
...
INSERT INTO DATES (FUTURE) VALUES (ADDDATE(CURDATE(), INTERVAL 14 DAY))
SELECT FUTURE FROM DATES WHERE FUTURE NOT IN (SELECT POSTDATE FROM POSTS)
DROP TABLE TEMPORARY DATES
END
I guess it just isn't possible to select the absence of data.
You're right — SQL does not make it easy to identify missing data. The usual technique is to join your sequence (with gaps) against a complete sequence, and select those elements in the latter sequence without a corresponding partner in your data.
So, #BenHoffstein's suggestion to maintain a permanent date table is a good one.
Short of that, you can dynamically create that date range with an integers table. Assuming the integers table has a column i with numbers at least 0 – 13, and that your table has its date column named datestamp:
SELECT candidate_date AS missing
FROM (SELECT CURRENT_DATE + INTERVAL i DAY AS candidate_date
FROM integers
WHERE i < 14) AS next_two_weeks
LEFT JOIN my_table ON candidate_date = datestamp
WHERE datestamp is NULL;
One solution would be to create a separate table with one column to hold all dates from now until eternity (or whenever you expect to stop blogging). For example:
CREATE TABLE Dates (dt DATE);
INSERT INTO Dates VALUES ('2011-01-01');
INSERT INTO Dates VALUES ('2011-01-02');
...etc...
INSERT INTO Dates VALUES ('2099-12-31');
Once this reference table is set up, you can simply outer join to determine the unused dates like so:
SELECT d.dt
FROM Dates d LEFT JOIN Blogs b ON d.dt = b.dt
WHERE b.dt IS NULL
If you want to limit the search to two weeks in the future, you could add this to the WHERE clause:
AND d.dt BETWEEN NOW() AND ADDDATE(NOW(), INTERVAL 14 DAY)
The way to extract rows from the mysql database is via SELECT. Thus you cannot select rows that do not exist.
What I would do is fill my blog table with all possible dates (for a year, then repeat the process)
create table blog (
thedate date not null,
thetext text null,
primary key (thedate));
doing a loop to create all dates entries for 2011 (using a program, eg $mydate is the date you want to insert)
insert IGNORE into blog (thedate,thetext) values ($mydate, null);
(the IGNORE keyword to not create an error (thedate is a primary key) if thedate exists already).
Then you insert the values normally
insert into blog (thedate,thetext) values ($mydate, "newtext")
on duplicate key update thetext="newtext";
Finally to select empty entries, you just have to
select thedate from blog where thetext is null;
You probably not going to like this:
select '2011-01-03', count(*) from TABLE where postdate='2011-01-03'
having count(*)=0 union
select '2011-01-04', count(*) from TABLE where postdate='2011-01-04'
having count(*)=0 union
select '2011-01-05', count(*) from TABLE where postdate='2011-01-05'
having count(*)=0 union
... repeat for 2 weeks
OR
create a table with all days in 2011, then do a left join, like
select a.days_2011
from all_days_2011
left join TABLE on a.days_2011=TABLE.postdate
where a.days_2011 between date(now()) and date(date_add(now(), interval 2 week))
and TABLE.postdate is null;