I am trying to summarize records using the following query in MySQL. It works great as long as there is at least one record in each year. If records are missing in years, then the year doesn't show up. How can I modify this to show each year within my filter?
SELECT SUM( SICK_SIZE + DEAD_SIZE ) AS Cases, DATE_FORMAT( EVENT_DATE, '%Y' ) AS DateYear
FROM report_case_ext
WHERE DATE_FORMAT( EVENT_DATE, '%Y' ) >= DATE_FORMAT( DATE_ADD( CURDATE( ) , INTERVAL -4YEAR ) , '%Y' )
AND DATE_FORMAT( EVENT_DATE, '%Y' ) <= DATE_FORMAT( CURDATE( ) , '%Y' )
GROUP BY DATE_FORMAT( EVENT_DATE, '%Y' )
In MySQL, you can use sqlvariables, join to any other table to simulate row creation -- which returns a valid result set of the years you are looking for, then LEFT-JOIN to your other table so you know you'll always get the years you want...
select
YearsYouWant.RequireYear as DateYear,
SUM( RCE.SICK_SIZE + RCE.DEAD_SIZE ) AS Cases
from
( select #nYear := #nYear +1 as RequireYear
from report_case_ext,
( select #nYear := year( curdate()) -5 ) sqlvars
limit 5 ) as YearsYouWant
LEFT JOIN
report_case_ext RCE
on YearsYouWant.RequireYear = year( RCE.Event_Date )
GROUP BY
YearsYouWant.RequireYear
The inner prequery that uses "report_case_ext" is only used to have a table of at least 5 records to keep the years you want... In this case,
#nYear is initialized to 1 year less than the 4 you were looking for -- hence -5
curdate() = 2013 - 5 = 2008.
Then, in the select #nYear := #nYear +1 first time will have the first year become 2009 and complete for 5 years, thus generating a record for 2009, 2010, 2011, 2012 and 2013 (via LIMIT 5)
Now that result (of all years) is LEFT-joined to the report_case_ext table on common years. So, even those that have no dates
Create a table contains all possibile year/month/date (depends on your needs).
Then left join the table.
What is the most straightforward way to pad empty dates in sql results (on either mysql or perl end)?
Related
I have this mysql query that does what it needs to but it takes a really long time to load the content where as my other queries run perfectly fine and quick. Is there a better way to do it? I just want it to load faster. Here is my query:
SELECT
DISTINCT( # Without this I get too many results
CONCAT_WS(' ',
MONTHNAME(a.DateTimeViewed),
YEAR(a.DateTimeViewed)
)
) AS ViewedDate, # Displays as "January 2017" (example)
(
SELECT COUNT(b.ViewID)
FROM views b
WHERE
MONTH(b.DateTimeViewed) = MONTH(a.DateTimeViewed) AND
YEAR(b.DateTimeViewed) = YEAR(a.DateTimeViewed)
) as TotalViews
FROM views a
WHERE a.DateTimeViewed >= date_sub(now(), interval 6 month)
ORDER BY YEAR(a.DateTimeViewed) ASC, MONTH(a.DateTimeViewed) ASC
You are working too hard.
SELECT CONCAT_WS(' ', MONTHNAME(a.DateTimeViewed), YEAR(a.DateTimeViewed)
) AS ViewedDate,
COUNT(*) as TotalViews
FROM views a
WHERE a.DateTimeViewed >= date_sub(now(), interval 6 month)
ORDER BY YEAR(a.DateTimeViewed) ASC, MONTH(a.DateTimeViewed) ASC
Since you are backing up 6 months from this instant, you are getting the count for only part of the first month. Perhaps you want to change one line:
WHERE a.DateTimeViewed >= CONCAT(LEFT(CURDATE() - INTERVAL 6 MONTH, 7), '-01')
COUNT(*) is the usual way to count rows. COUNT(x) does the same, but adds on the effort to filter out rows with x IS NULL.
Im trying to retrieve data to make statistics, im using mySQL and i cant get the following function to work - the postgreSQL is working.
I want to retrieve the request for the last month and count the amount of new requests for each day.
postgreSQL
SELECT count(*), date_trunc('day', created_at) as date FROM requests
WHERE(created_at > '2014-08-13 00:00:00') GROUP BY 2 ORDER BY 2 ASC;
*mySQL - my code *
SELECT count(EXTRACT(DAY FROM created_at)), EXTRACT(DAY FROM created_at) as date
FROM `requests`
WHERE EXTRACT(DAY FROM NOW() - INTERVAL 1 MONTH)
GROUP BY date
Final code
SELECT count( * ) , date( created_at ) AS date
FROM `requests`
WHERE DATE( created_at ) > DATE( DATE_SUB( NOW( ) , INTERVAL 1 MONTH ) )
GROUP BY date
The equivalent for your case is date():
select date(created_at), count(*)
from requests
. . .
This isn't a general replacement, but it works to remove the time portion of a date.
EDIT:
Perhaps the better solution for these two databases is:
select cast(created_at as date)
This is ANSI standard and works in both these databases (as well as SQL Server). I personally don't use this in general, lest I accidentally use it in Oracle, causing difficult to find errors. (dates in Oracle have a time component, alas.)
SELECT Name, doB, Age CURDATE( ) , (
YEAR( CURDATE( ) ) - YEAR( F )
) - ( RIGHT( CURDATE( ) , 5 ) < RIGHT( F, 5 ) ) AS Ages
SELECT Name, DoB, Ages WHERE Age=20 As Age
FROM Table_
ORDER BY N
Where do I put the the where AGES=20 if I want to only display the names of people that are 20 years old if the Age column is a temp column?
-- edit --
The oryginal query is:
SELECT N, F, CURDATE( ) ,
( YEAR( CURDATE( ) ) - YEAR( F ) )
- ( RIGHT( CURDATE( ) , 5 ) < RIGHT( F, 5 ) ) AS Age
FROM edad_ LIMIT 0 , 30
I can't make heads or tails of your query.
But to answer your question, a predicate on a derived column is not allowed in a WHERE clause, but it can be included in a HAVING clause. For example:
SELECT t.DoB
, TIMESTAMPDIFF(YEAR, t.DoB, CURDATE()) AS age
FROM mytable t
HAVING age = 20
BUT...
Be aware of performance issues. Note that the HAVING clause is applied very late in the processing of the query, after all of the rows have been retrieved and prepared. It acts more like a filter on the rows that are returned, while the WHERE clause acts as a filter on the rows retrieved, processed much earlier in the query.
For performance on large sets, we typically want to benefit from index range scans, so we use an equivalent predicate on a native column. (If a an appropriate index is available.)
For example, if an index on DoB is available:
SELECT t.DoB
, TIMESTAMPDIFF(YEAR, t.DoB, CURDATE()) AS age
FROM mytable t
WHERE t.DoB >= CURDATE() + INTERVAL -21 YEAR
AND t.DoB < CURDATE() + INTERVAL -20 YEAR
(NOTE: You may need to replace >= with > and replace < with <= to get the age calculation working the way you want on the edge cases of CURDATE is exactly 20 years or exactly 21 years from DoB.)
I read many topics to fetch data that posted in different periods, but as the Time in my mysql table is in STRING format I couldn't make it happen.
SELECT s.user_id, count(*) AS wins, u.username, u.avatar,u.avatar_uploaded
FROM on_scores AS s
LEFT JOIN on_users AS u ON (u.userid = s.user_id)
WHERE s.is_high = '1' AND DATE(s.date_score) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY s.user_id
ORDER BY wins DESC
LIMIT 10
I tried the STR_TO_DATE method but still no output.
Use the from_unixtime function to get the time into a date-like format.
More info here.
Information on formatting the resultant date - here.
Example:
select date_sub( from_unixtime( s.datescore ), INTERVAL 1 MONTH ) as monthfromdatevalue;
select datediff( from_unixtime( s.datescore, curdate()) as howlongago_fromtoday;
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
MySQL Query GROUP BY day / month / year
I have php timestamps (e.g. 1307362819) stored in a column in my database. I want to group count(*) in days, weeks and months the data.
For example I want to find out how many entries there are per day, per week, and per month etc.
How can this be achieved?
You can subtract day, week and month value from a timestamp, and group the subtracted values.
grouping by day value:
select count(*) from table group by from_unixtime(timeStampColumn, '%Y%m%d')
grouping by week value:
select count(*) from table group by from_unixtime(timeStampColumn, '%Y%m%u')
grouping by monthvalue:
select count(*) from table group by from_unixtime(timeStampColumn, '%Y%m')
For more information, have a look at this page: http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html
Why don't you use these: <>
SELECT COUNT(*) FROM yourTable WHERE yourTimestampField > someTimestampAWeekPast;
SELECT COUNT(*) FROM yourTable WHERE yourTimestampField > someTimestampADayPast;
Use the mysql date/time functions http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html to calculate the desired date in the past.
Use UNIX_TIMESTAMP if you stored them as int or string or whatever.
here a good exemple for you
to group by week
EDIT:
try this
select
id_user,
year(time) as AYear, week(time) as AWeek, day(time) as Aday ,
count(week(time)) as TotalPerWeek , count(day(time)) as TotalPerDay ,
count(year(time)) as TotalPerYear
from yourtable
where id_user = 16 //// the user u want to check
group by id_user, AYear, AWeek , Aday
order by AYear, AWeek , Aday
SELECT MONTH( FROM_UNIXTIME( `timeStamp` ) ) , COUNT( `id` )
FROM `discusComments`
GROUP BY MONTH( FROM_UNIXTIME( `timeStamp` ) )