TIMESTAMPDIFF, multiple row results on new column - mysql

I have a student database which has a date of enrolment column. I need to run a query on sql that lets look up this date and today's date, and display the difference in yy Years mm Months.
I'm using TIMESTAMPDIFF to work out the difference between these dates but can only produce one value, how can I adapt it to work it out for the entire row? i need to create a new column with this data.
This is the query:
SELECT TIMESTAMPDIFF(MONTH, CURDATE(), (SELECT time_enrolled FROM student) )
AS newDate
If I add a "where" statement at the end i get the specified id for example:
SELECT TIMESTAMPDIFF(MONTH, CURDATE(), (SELECT time_enrolled FROM student WHERE f_id = 4) )
AS newDate

Don't use a subquery. Your original query should be:
SELECT TIMESTAMPDIFF(MONTH, CURDATE(), time_enrolled) AS newDate
FROM student;
The subquery will generate an error if it returns more than one row in a scalar context -- such as returning a value in the select statement.
You can add an appropriate where clause to this query if you like.
EDIT:
To get years and months, use modulo arithmetic:
SELECT floor(TIMESTAMPDIFF(MONTH, CURDATE(), time_enrolled) / 12) as years,
mod(TIMESTAMPDIFF(MONTH, CURDATE(), time_enrolled), 12) as months
FROM student;

Related

select rows as month according to timestamp

I have a table - accounts, and it has 3 columns: id , timestamp and value.
I need to create a query that returns a table which in each row it will be the month (2, 3, etc.) and the sum of the values from this month.
for example: if my table will have 3 rows from January and one row from February, the query will return a two-rows table within the first row it'll be 1 and the sum of January's values, and the second will be 2 and the sum of February's values.
I have no idea how to begin. can anyone help me?
all you need to do is sum the value and also use mysql's MONTH() function to pull out the month from your timestamp
SELECT SUM(value) as total_amount, MONTH(timestamp) as month_num
FROM table
GROUP BY month_num
GROUP BY is used when you have an aggregate function (in our case its SUM) to know how to group your common fields. without a group by you will have all rows summed together
SQL Server can use the DATEPART function.
SELECT DATEPART(MONTH, your_date_column) AS month_
, SUM(your_value) AS value_
FROM your_table
GROUP BY DATEPART(MONTH, your_date_column)

Select leave data from attendance table given the following condition

I have attendance data for employees stored in the table attendance with the following column names:
emp_id (employee ID)
date
type (leave, absent, etc.)
(there are others but I'm omitting them for the sake of simplicity)
My objective is to retrieve all dates of the given month on which the employee was on leave (type = 'Leave') and the last leave taken in the last month, if any.
It's easy to do it using two queries (I'm using PHP to get process the data), but is there any way this can be done in a single query?
I'm answering my own question so as to close it. As #bpgergo pointed out in the comments, UNION will do the trick here.
SELECT * FROM table_name
WHERE type="Leave" AND
date <= (CURRENT_DATE() - 30)
Select the fields, etc you want then se a combined where clause using mysql's CURRENT_DATE() function. I subtracted 30 for 30 days in a month.
If date is a date column, this will return everyone who left 1 month or longer ago.
Edit:
If you want a specific date, change the 2nd month like this:
date <= (date_number - 30)

Nested MySQL Query w/ concat and adddate

I am trying to nest a few queries but so far am getting back error 1242: Subquery returns more than 1 row. I want more than one row, as I am working on a number of records.
I have 2 tables. One has a commencement date stored in 3 columns; yr_comm, mth_comm, day_comm. The 2nd table has a period of service (in years) for a number of users which is expressed as an integer (2.71, 3.45, etc).
I need to take this start date (from table 1), and add on the period of service (from table 2) to obtain an end date, but I only need to display the year.
I have 2 queries which work just fine when seperate, they result in the required values, however I am having trouble combining the queries to get the desired end result.
Query 1: Concatenate the 3 commencement values into date format
SELECT concat_ws('-', yr_comm, mth_comm, day_comm) AS date_comm
FROM table 1
Query 2: Convert the integer yrs_service into days
SELECT format(yrs_served * 365, 0) AS days_served
FROM table 2
Query 3: Use date_add function to add the days service to the commencement date
SELECT date_add(date_comm, INTERVAL days_served DAY) AS date_left
Can anyone suggest how I can achieve the above? Many thanks in advance.
EDIT - Here is the full query I am working on:
SELECT prime_minister.pm_name, yr_comm, party, ADDDATE(
(SELECT CONCAT_WS('-', yr_comm, mth_comm, day_comm) FROM ministry), INTERVAL
(SELECT FORMAT(yrs_served * 365, 0) FROM prime_minister) YEAR) AS date_left
FROM ministry JOIN prime_minister USING (pm_name)
WHERE party NOT LIKE '%labor%'
AND prime_minister.pm_name = ministry.pm_name
ORDER BY pm_name;
you can use user variables
SET #date = CONCAT_WS('-', 2012,1,1); -- paste your query here
SET #toAdd = (SELECT MONTH(CURDATE())); -- paste your query here
SELECT DATE_ADD(#date, INTERVAL #toAdd DAY) AS date_left
SQLFiddle Demo
which is the same as
SET #date = CONCAT_WS('-', 2012,1,1); -- paste your query here
SET #toAdd = (SELECT MONTH(CURDATE())); -- paste your query here
SELECT #date + INTERVAL #toAdd DAY AS date_left
SQLFiddle Demo
or without using variable, which is more longer,
SELECT (CONCAT_WS('-', 2012,1,1)) + INTERVAL (SELECT MONTH(CURDATE())) DAY AS date_left
SQLFiddle Demo

Retrieving all records based on a specific month in MySQL

my dates in my table are strings in the format:
"10/12/2009"
Now how would one get all the records from a month, lets say June (number "6" being provided)?
Check the MySQL function STR_TO_DATE.
You should not store dates as string, however. Use the type DATE.
The short answer to your question is that you can use the STR_TO_DATE and MONTH functions to 1) convert the string representation into a DATE, and 2) extract the month component from the date:
SELECT t.*
FROM mytable t
WHERE MONTH(STR_TO_DATE(t.dateasstringcol,'%M/%d/%Y')) = 6
(This is assuming here that by '10/12/2009', you are specifying Oct 12, and not Dec 10. You'd need to adjust the format string if that's not the case.)
Alternatively, if month is indeed the leading part of the date, you could do a simple string comparison, if the month is the leading component:
SELECT t.*
FROM mytable t
WHERE t.dateasstringcol LIKE '6/%'
OR t.dateasstringcol LIKE '06/%'
(You could eliminate one of those predicates, if you have an exact format specified for the striing value representing the date: either if month is always stored as two digits -OR- the month is never stored with a leading zero.)
If you are passing in an argument for the month, e.g. '6', then you could construct your statement something like this:
WHERE t.dateasstringcol LIKE '6' + '/%'
If month is the second component of the date, then you could use:
SELECT t.*
FROM mytable t
WHERE t.dateasstringcol LIKE '%/' + '6' + '/%'
OR t.dateasstringcol LIKE '%/' + '06' + /%'
NOTE:
All of the previous example queries will return rows for June of any year (2009, 2010, 2011)
You can extend those examples, and do something similar with the year, using the YEAR function in place of the MONTH function, or for string comparison
AND t.dateasstringcol LIKE '%/%/2011'
Normally, we'd extract rows for a particular month for a particular year, using a date range, for example:
SELECT t.*
FROM mytable t
WHERE MONTH(STR_TO_DATE(t.dateasstring,'%M/%d/%Y')) >= '2011-06-01'
AND MONTH(STR_TO_DATE(t.dateasstring,'%M/%d/%Y')) < '2011-07-01'
Of course, when the date value is stored as a DATE datatype rather than as a VARCHAR, this means we don't need the STR_TO_DATE and MONTH functions, we can specify a comparison to the native DATE column. This approach allows us to make use of an index on the date column, which can improve query performance on large tables.
SELECT t.*
FROM mytable t
WHERE t.realdatecol >= '2011-06-01'
AND t.realdatecol < '2011-07-01'
The STR_TO_DATE function is your friend here:
SELECT * FROM my_table
WHERE STR_TO_DATE('10/12/2009','%M/%d/%Y') >= '2012-06-01';
MONTH should help here if we want current month or particular month data. e.g:
$month = date('m'); OR particular month.
SELECT * FROM users WHERE MONTH(str_to_date("10/12/2009",'%e/%m/%Y')) = $month;

Some questions about SQL group by week

I have some problems when coding SQL group by week.
I have a MySQL table named order.
In this entity, there are several attributes, called 'order_id', 'order_date', 'amount', etc.
I want to make a table to show the statistics of past 7 days order sales amount.
I think first I should get the today value.
Since I use Java Server Page, the code like this:
Calendar cal = Calendar.getInstance();
int day = cal.get(Calendar.DATE);
int Month = cal.get(Calendar.MONTH) + 1;
int year = cal.get(Calendar.YEAR);
String today = year + "-" + Month + "-" + day;
then, I need to use group by statement to calculate the SUM of past 7 day total sales amount.
like this:
ResultSet rs=statement.executeQuery("select order_date, SUM(amount) " +
"from `testing`.`order` GROUP BY order_date");
I have problem here. In my SQL, all order_date will be displayed.
How can I modify this SQL so that only display past seven days order sale amount?
Besides that, I discover a problem in my original SQL.
That is, if there is no sales on that day, no results would be displayed.
OF course, I know the ResultSet does not allow return null values in my SQL.
I just want to know if I need the past 7 order sales even the amount is 0 dollars,
Can I have other methods to show the 0?
Please kindly give me advices if you have idea.
Thank you.
Usually it occurs to create with a script or with a stored procedure a calendar table with all dates.
However if you prefer you can create a table with few dates (in your case dates of last week) with a single query.
This is an example:
create table orders(
id int not null auto_increment primary key,
dorder date,
amount int
) engine = myisam;
insert into orders (dorder,amount)
values (curdate(),100),
(curdate(),200),
('2011-02-24',50),
('2011-02-24',150),
('2011-02-22',10),
('2011-02-22',20),
('2011-02-22',30),
('2011-02-22',5),
('2011-02-19',10);
select t.cdate,sum(coalesce(o.amount,0)) as total
from (
select curdate() -
interval tmp.digit * 1 day as `cdate`
from (
select 0 as digit 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 ) as tmp) as t
left join orders as o
on t.cdate = o.dorder and o.dorder >= curdate() - interval 7 day
group by t.cdate
order by t.cdate desc
Hope that it helps. Regards.
To answer your question "How can I modify this SQL so that only display past seven days order sale amount?"
Modify the SQL statement by adding a where clause to it:
Where order_date >= #date_7days_ago
The value for this #date_7days_ago date variable can be set before your statement:
Select #date_7days_ago = dateadd(dd,-7,getdate())
Adding that where clause to your query will return only those records which order date is in the last seven days.
Hope this helps.
You can try using this:
ResultSet rs = statement.executeQuery(
"SELECT IFNULL(SUM(amount),0)
FROM table `testing`.`order`
WHERE order_date >= DATE_SUB('" + today + "', INTERVAL 7 DAY)"
);
This will get you the number of orders made in the last 7 days, and 0 if there were none.