php - SQL week of year() to string/date - mysql

I run a query against a MySQL database to get total number of visits grouped by week.
The structure of the table is:
|ID (int) | SESSION (char) | TIMESTAMP (datetime) |
My query looks like this:
'SELECT COUNT(session), WEEKOFYEAR(timestamp)
FROM stats
GROUP BY WEEKOFYEAR(timestamp)
ORDER BY timestamp ASC';
So I get an array of week numbers eg 40,41,45 etc, along with the view count.
How can I convert this into readable date (using PHP)? It's not practical to say, "Week number 40-something: 2000 visits".
I'm looking for something in the form of StartDate-EndDate/Month/Year, eg. Week 5-11/12/2011, Visits: XXXX.
Any functions you might have used before? I've tried but with no luck.
Is my SQL query a correct way to do it? Assuming that I'm querying the db correctly for what I'm trying to accomplish, is there a way to convert a week number into a day/date span?
I'm also wondering what will happen if a week spans between two months or even two years.

Assumptions:
The date you want to display is the Monday Week Date for that week
Your main output is Week <week number>-<monday date of week>, Visits: <count>.
You know enough PHP to be able to pull the column Phrase
The following SQL command should display for you the count of sessions per week of year, the week of year, and your desired phrase:
SELECT COUNT(session) AS VisitCount
, WEEKOFYEAR(timestamp) AS WeekOfYear_Value
, MAKEDATE(
CASE
WHEN WEEKOFYEAR(timestamp) = 52
THEN YEAR(timestamp)-1
ELSE YEAR(timestamp)
END, (WEEKOFYEAR(timestamp) * 7)-4) AS DateOfWeek_Value
, CONCAT('Week ', WEEKOFYEAR(timestamp)
, '-', MAKEDATE(
CASE
WHEN WEEKOFYEAR(timestamp) = 52
THEN YEAR(timestamp)-1
ELSE YEAR(timestamp)
END, (WEEKOFYEAR(timestamp) * 7)-4) -- Monday
, ', Visits: ' , COUNT(session), '.') AS Phrase
FROM stats
GROUP BY WEEKOFYEAR(timestamp)
ORDER BY timestamp ASC
Try it out on your existing data.
[edit : additional code changes]
To get you the Sunday output:
SELECT COUNT(session) AS VisitCount
, WEEKOFYEAR(timestamp) AS WeekOfYear_Value
, CONCAT('Week ', WEEKOFYEAR(timestamp)
, '-', MAKEDATE(
CASE
WHEN WEEKOFYEAR(timestamp) = 52
THEN YEAR(timestamp)-1
ELSE YEAR(timestamp)
END,
CASE
WHEN WEEKOFYEAR(timestamp) = 52
THEN (WEEKOFYEAR(timestamp) * 7)+3
ELSE (WEEKOFYEAR(timestamp) * 7)+2
END
)
, ', Visits: ' , COUNT(session), '.') AS Phrase
FROM stats
GROUP BY WEEKOFYEAR(timestamp)
ORDER BY timestamp ASC
Also notice that this last update includes another CASE in the makedate command, to ensure consistency between dates from the current and last year values.

Related

create a ranking and statistics with repeated database records

Today I want to get a help in creating scores per user in my database. I have this query:
SELECT
r1.id,
r1.nickname,
r1.fecha,
r1.bestia1,
r1.bestia2,
r1.bestia3,
r1.bestia4
r1.bestia5
FROM
reporte AS r1
INNER JOIN
( SELECT
nickname, MAX(fecha) AS max_date
FROM
reporte
GROUP BY
nickname ) AS latests_reports
ON latests_reports.nickname = r1.nickname
AND latests_reports.max_date = r1.fecha
ORDER BY
r1.fecha DESC
that's from a friend from this site who helped me in get "the last record per user in each day", based on this I am looking how to count the results in a ranking daily, weekly or monthly, in order to use statistics charts or google datastudio, I've tried the next:
select id, nickname, sum(bestia1), sum(bestia2), etc...
But its not giving the complete result which I want. That's why I am looking for help. Additionally I know datastudio filters where I can show many charts but still I can count completely.
for example, one player in the last 30 days reported 265 monsters killed, but when I use in datastudio my query it counts only the latest value (it can be 12). so I want to count correctly in order to use with charts
SQL records filtered with my query:
One general approach for get the total monsters killed by each user on the latest X days and make a score calculation like the one you propose on the commentaries can be like this:
SET #daysOnHistory = X; -- Where X should be an integer positive number (like 10).
SELECT
nickname,
SUM(bestia1) AS total_bestia1_killed,
SUM(bestia2) AS total_bestia2_killed,
SUM(bestia3) AS total_bestia3_killed,
SUM(bestia4) AS total_bestia4_killed,
SUM(bestia5) AS total_bestia5_killed,
SUM(bestia1 + bestia2 + bestia3 + bestia4 + bestia5) AS total_monsters_killed,
SUM(bestia1 + 2 * bestia2 + 3 * bestia3 + 4 * bestia4 + 5 * bestia5) AS total_score
FROM
reporte
WHERE
fecha >= DATE_ADD(DATE(NOW()), INTERVAL -#daysOnHistory DAY)
GROUP BY
nickname
ORDER BY
total_score DESC
Now, if you want the same calculation but only taking into account the days of the current week (assuming a week starts on Monday), you need to replace the previous WHERE clause by next one:
WHERE
fecha >= DATE_ADD(DATE(NOW()), INTERVAL -WEEKDAY(NOW()) DAY)
Even more, if you want all the same, but only taking into account the days of the current month, you need to replace the WHERE clause by:
WHERE
MONTH(fecha) = MONTH(NOW())
For evaluate the statistics on the days of the current year, you need to replace the WHERE clause by:
WHERE
YEAR(fecha) = YEAR(NOW())
And finally, for evaluation on a specific range of days you can use, for example:
WHERE
DATE(fecha) BETWEEN CAST("2018-10-15" AS DATE) AND CAST('2018-11-10' AS DATE)
I hope this guide will help you and clarify your outlook.
This will give you number of monster killed in the last 30 days per user :
SELECT
nickname,
sum(bestia1) as bestia1,
sum(bestia2) as bestia2,
sum(bestia3) as bestia3,
sum(bestia4) as bestia4,
sum(bestia5) as bestia5
FROM
reporte
WHERE fecha >= DATE_ADD(curdate(), interval -30 day)
GROUP BY nickName
ORDER BY

SQL - Performing a query on a result from another query?

I have a column(varchar) with date values, I need to find those dates which are expiring in next 30 days.
ExpiringDate
===================
20171208,
20171215,samples
20171130,tested
N/A
No
(empty row)
So, First I need to get values before comma. On the resultset, I need to filter out rows that has only numbers(no 'N/A' or 'No' or empty rows) & then I need to filter those dates which are expiring in next 30 days.
Edited
I have tried the following & resultset seems to be inappropriate
SELECT
DocName,
CategoryName,
AttributeName,
CAST(SUBSTRING_INDEX(AttributeValue, ',', 1) AS DATE) AS ExpiredDate
FROM myDB
WHERE (AttributeName = 'Date of last vessel OVID' OR AttributeName = 'Next Statutory docking' OR
AttributeName = 'Last statutory docking') AND AttributeValue LIKE '%[^0-9]%' AND
DATEDIFF(now(), AttributeValue) <= 30;
Because you are not only storing dates as text, but mixing those dates with entirely non date information, this complicates things. In this case, we can do two checks, one to ensure that the record starts with an actual expected date, and the second to make sure that the date diff is within 30 days from now.
SELECT ExpiringDate
FROM
(
SELECT ExpiringDate
FROM yourTable
WHERE ExpiringDate REGEXP '^[0-9]{8}'
) t
WHERE
DATEDIFF(LEFT(ExpiringDate, 8), NOW()) BETWEEN 0 AND 30;
Note that I use a subquery to first remove rows that do not even have a parseable date. The reason for this is that DATEDIFF will error out if not passed valid dates for both parameters.
Demo

ORDER BY datetime depending on the day AND time

I have a database field of type datetime.
The name of this field is "recallDate"
I would like to order the results in the following way:
The results must be chronological in the time: from newest to oldest
The results must be grouped by date: in other words, result having the same date are together, grouped
For every day, the results must be chronological according to the hour: earliest to latest
The results having no hour ( 00:00:00 ) have to be at the end of the results of the day
This is my actual query :
SELECT a.recallDate, a.id, a.id_company, com.name, a.recallType
FROM PDT_CRM.actions a
INNER JOIN PDT_CRM.traders as trad on trad.id=a.id_traders
WHERE DATE(a.recallDate) > DATE(NOW() + INTERVAL 30 DAY)
ORDER BY TIME(a.recallDate) , a.recallType
It is very likely that I have to use CASE but I don't understand how to use it.
You can use the following code to create a specific order that will put times '00:00:00' at the very end of the day:
...
ORDER BY date(a.rappelDate),
case when time(a.rappelDate) = 0 then 1 else 0 end,
time(a.rappelDate)

Check if date range is in month (calendar)

I'm trying to check with sql if a date range (with start and end date) is in a month (regarding year). Month and year are given variables (GET-variables).
This is my table:
+----+------+-------+-----+
| id | name | start | end |
+----+------+-------+-----+
Because an appointment could be just one date (start and end would be the same date), I have to consider this.
My query
SELECT
id,
name,
start,
end
FROM appointments
WHERE (MONTH(start) = ? AND YEAR(end) = ?) OR (MONTH(start) = ? AND YEAR(end) = ?)
ORDER BY start
The problem with this query is that it just checks the start-month and the end-month not the months between. For example if an appointment is over 5 months, this query fails.
If you want to know if a particular month is in the range, then I would suggest turning the dates into a YYYYMM format. This makes the logic relatively easy to express:
where ?*100 + ? between year(start)*100 + month(start) and
year(end)*100 + month(end)

How to get data from mysql and group them in weeks, also separating by month

I have mysql database and is full of over 2 years of data. How can I make a query in a way that it will get the result as below?:
January
Week 1
...
data rows here
....
Week 2
...
...
Week 3
...
...
Week 4
...
...
February (same as above)
These are the field structures:
- date (in yyyy-mm-dd format)
- job (integer autoincrement)
- person (varchar)
Try this, it will generate output pretty similar to one required by you
SELECT MONTH(date) AS MONTH, WEEK(date) AS WEEK, DATE_FORMAT(date, %Y-%m-%d) AS DATE, job AS JOB, person AS PERSON GROUP BY WEEK(date);
GROUP BY year(record_date), MONTH(record_date)
Check out the date and time functions in MySQL.
It has to be a query, or you can use ajax too? Using ajax you could do a loop in javascript:
date = [initial date]
while date <= [final date] {
divUpdate = 'divrecs'; // will be used in updateDiv function
url = 'getrecs.php?date1='+date+'&date2='+(date+6);
conecta(url,updateDiv);
date = date+7;
}
And inside getrecs your query would be:
$stmt = $dbh->prepare("select * from yourtable where date >= '".$_GET['date1']."' and date <= '".$_GET['date2']."'");
if ($stmt->execute()) {
while ($row = $stmt->fetch(PDO::FETCH_BOTH)) {
echo "Do anything with your data here: $row[1] etc<BR>";
}
}
Hope that helps!
SELECT
MONTH(created_datetime) AS month,
WEEK(created_datetime) AS week,
DATE(created_datetime) AS date,
COUNT(id) AS count
FROM users
WHERE date(created_datetime) BETWEEN '2017-05-01' AND '2017-12-31'
GROUP BY month
ORDER BY created_datetime
If you want records date wise that you need to use GROUP BY date.
If you want records weekly that you need to use GROUP BY week.
If you want records monthly that you need to use GROUP BY month.