What can be the optimized query for this? - mysql

I have stuck in small query. There is a table named Table_Activities.
Table_Activities (Act_id, Date, Activity_name, description).
We need to generate a report out of this. User will choose the month and year for which he wants to generate the report from drop down list.
We need to display All the activities for that month and year group by Activity name.
Example - User Chooses June and 2012.
Report will be-
Gardening
01/06/2012 - They have planted 100 trees.
14/06/2012 - something
27/06/2012 - something
Training
02/06/2012 - Detail description
15/06/2012 - something
28/06/2012 - something
My question is what will be the mysql query to fetch data in this format??

select `Date`,description from tm_activities
where month(`Date`)='6' and year(`Date`)='2012'
order by Activity_name,`date`
To return an exact format as indicated in your question, please try below:
select concat(if(actdate='',activity_name,date_format(actdate,'%d/%m/%y')),if(description<>'',concat(' - ',description),'')) as labelm from
(
(select ActDate,description,activity_name from tm_activities where month(ActDate)='6' and year(ActDate)='2012'
)
union all
(Select distinct '','',activity_name from tm_activities where month(ActDate)='6' and year(ActDate)='2012')
)m order by activity_name,actdate
;
SQL FIDDLE HERE.
Output as below:
Gardening
01/06/12 - They have planted 100 trees.
27/06/12 - Gar 2
Training
12/06/12 - Training 1
28/06/12 - Traning 2
30/06/12 - Traning 3

To get data for particular month and year group by Activity_name try this:
SELECT Activity_name
,GROUP_CONCAT(DATE_FORMAT(Date,"%d/%m/%Y")) as `Date`
,GROUP_CONCAT(Description) as `Description`
FROM Table_Activities
WHERE MONTH(Date) = MONTH('2012-06-01')
AND YEAR(Date) = YEAR('2012-06-01')
GROUP BY Activity_name
Output
ACTIVITY_NAME DATE DESCRIPTION
-----------------------------------------------------------------------------------
Gardening 01/06/2012,27/06/2012 They have planted 100 trees.,Description3
Training 12/06/2012,28/06/2012 Description2,Description4
See this SQLFiddle

Select
DATE_FORMAT('date_column',"%D/%M/%Y") as `Date`,
other_column
from Table_Activities
where Month(Date) = Month('2012-06-01')
AND Year(Date) = Year('2012-06-01')

Related

MySQL Query Filter Sequenced by two date columns

I wanted to arranged my table in a proper sequence of date to both the date_due column and date_paid column.
My table structure shows like this and it is ordered by the due_date column:
Period Due Date Paid Date
12/01/2014
02/05/2014
1 01/01/2015
2 02/01/2015
3 03/01/2015
4 04/01/2015
Then all I want is to do this:
Period Due Date Paid Date
12/01/2014
1 01/01/2015
2 02/01/2015
02/05/2014
3 03/01/2015
4 04/01/2015
Ok forget about my stupid comment - it was not constructive. First of all I think you have a mistake in your data: I guess "02/05/2014" should be "02/05/2015".
The problem is that you have to aggregate the two columns, to be able to sort after that. Using the GREATEST function like I stated in my comment actually would not work, because it is not null-save. You can use for example the COALESCE function here.
All in all this can either be done by "adding a column" like
SELECT
*, Coalesce(`Due Date`, `Paid Date`) as bananas
FROM
table1
ORDER BY
bananas
Or add the expression directly to the ORDER BY clause:
SELECT
*
FROM
table1
ORDER BY
Coalesce(`Due Date`, `Paid Date`)
Please see this fiddle and try yourself: http://sqlfiddle.com/#!2/21a84/1

mysql query to fetch the quarter month from table

Table name: activity
Field name: ProcessYM
I have mysql data like below.
ProcessYM
==========
201312
201311
201310
201309
201308
201307
201306
201305
201304
201303
201302
201301
201212
201211
201210
201209
201208
201207
201206
I want to fetch the result like below. I mean, the mysql query to fetch the every quarter of the year like 201312, 201309, 201306, 201303, 201212, 201209.. and so on.
Actual Output I expect
=======================
ProcessYM
201312
201309
201306
201303
201212
201209
201206
I have tried the below query, but it does not produce the expected result.
SELECT distinct `ActProcessYM` from `activity` where `ActProcessYM`%3=0 order by ActProcessYM desc
Output of above query
=====================
201312
201309
201306
201303
201210
201207
It is much appreciated for your smart reply.
You need to modulo of the month part only. Your query is implicitly casting your ProcessYM as an INT.
For example:
SELECT DISTINCT ProcessYM
FROM activity
WHERE RIGHT(ProcessYM,2)%3=0
ORDER BY ProcessYM DESC
fiddle
you should retrieve the last two digits from field value and do the logic as you are doing.
SELECT distinct `ActProcessYM` from `activity` where substring(ActProcessYM,5,2)%3=0 order by ActProcessYM desc
Here's a not-so-quick-and-dirty way of handing this date processing. I believe you're looking for a MySQL formula like this:
yyyymm = TRUNC_QUARTER(yyyymm)
That is, you are looking for a function that converts any yyyymm month notation into a notation that shows the month that ends the quarter in question.
Let's start with an expression that converts any particular DATETIME expression to the DATE of the beginning of the quarter.
DATE(CONCAT(YEAR(value),'-', 1 + 3*(QUARTER(value)-1),'-01'))
This takes a timestamp (e.g. '2011-04-20 11:15:01') and turns it into the date of the starting of the quarter. (e.g. '2011-04-01')
Having things in this date form is helpful because you can use them for date arithmetic. For example, you can get the last day of that quarter like this.
DATE(CONCAT(YEAR(value),'-', 1 + 3*(QUARTER(value)-1),'-01'))
+ INTERVAL 1 QUARTER - INTERVAL 1 DAY
Here's a writeup on all this: http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/
I've found it helpful to try to stick to the date datatype when processing time series data.
You need to separate out the month value before doing the modulo 3 (% 3). Doing a modulo 100 first will do it:
(ProcessYM % 100) % 3) = 0
or
mod(mod(ProcessYM,100),3) = 0
Try this,
SELECT distinct `ProcessYM` from `activity` where SUBSTRING(`ProcessYM`,5,2)%3=0 order by ProcessYM desc

Specified condition on single selection in mysql query

I am using the following query to create a report. My problem comes from the fact that I need to use COUNT(market) for the year to date (total) of each 'market' then I also need a COUNT of 'market' for only the user imputed month ($mon). I cannot find any reference to using a WHERE on only a single selected field, everything else works as intended giving me the market with the percentages and year to date totals.
I need to make the line "COUNT(market) AS Saves" only count markets who's month field equals $mon and everything else to stay as is.
SELECT market,
COUNT(market) AS Saves,
COUNT(market) / (SELECT COUNT(*) FROM savedata2013) * 100 AS Percent,
COUNT(market) AS YTD
FROM savedata2013, ticket_info
GROUP BY market
ORDER BY COUNT(market) DESC';
Example Data:
market - Saves(June) - Percent - YTD
Los Angeles - 530 - 16.5154 - 564
San Jose - 390 - 12.1523 - 415
Irvine - 371 - 11.5373 - 394
You can use an if statement inside a sum, something like...
select sum(if(field='$mon',1,0)) as something....
I've created a SQLFiddle based on what I think your database might look like, and then run the following query.
So, the DB I used is defined as a market and an enteredDate. You probably have a lot more information in your ticket_info, but it shouldn't be relevant.
create table ticket_info (market varchar(20),
enteredDate DateTime);
And the query is:
SELECT market,
sum(if(monthname(enteredDate)='June',1,0)) AS `Saves(June)`,
sum(if(monthname(enteredDate)='June',1,0))/ (SELECT count(*) FROM ticket_info WHERE year(enteredDate) = 2013) AS Percent,
sum(if(year(enteredDate)=2013,1,0)) AS YTD
FROM ticket_info
GROUP BY market
ORDER BY `Saves(June)` DESC;
The percent will be null if there are no tickets entered for the year, but this should be an edge condition.
Link to SQLFiddle
You can probably resolve the problem like this, using CASE statement:
SELECT market,
COUNT
(
CASE market
WHEN month = $mon
THEN market
ELSE NULL
END
) AS Saves,
COUNT(market) / (SELECT COUNT(*) FROM savedata2013) * 100 AS Percent,
COUNT(market) AS YTD
FROM savedata2013, ticket_info
GROUP BY market
ORDER BY COUNT(market) DESC';

In SQL date function for before 2 months

I mentioned database table structure below,
name, expired_date, address, payment_date
----------------------
name1, 2013/06/02, address1,2013/07/23
name2, 2013/06/02, address2,2013/07/23
name3, 2013/04/02, address3,2013/07/23
name4, 2013/05/02, address4,2013/07/23
name5, 2013/06/02, address5,2013/07/24
...
name6, 2013/06/02, address6,.....
In this table I update date in yyyy/mm/dd format . current month is April but I need after two records only.
For example I need 06 month records only.
I need SQL query for this.
Assuming you want to query by expired_date:
Following query gets records after two months from current date:
SELECT * FROM tableName where expired_date>=DATE_ADD(CURDATE(), INTERVAL 1 MONTH)
If you specifically want records for June:
SELECT * FROM tableName where expired_date>='2013-06-01' AND expired_date<'2013-07-01'
Try it.
Select [fields] from [yourtable] where Month([yourDateField]) = [Value, ex: for June : 6]
Implement
I am assuming you want to check expired_date
Select * from Table1 where Month(expired_date) = 6
if you want to check year also then, assuming year is 2013.
Select * from Table1 where Month(expired_date) = 6 and Year(expired_date) = 2013

Query a MySQL Database and Group By Date Range to Create a Chart

I'm looking to create the following chart from a MySQL database. I know how to actually create the chart (using excel or similar program), my problem is how to get the data needed to create the chart. In this example, I can see that on January 1, 60 tickets were in the state illustrated by the green line.
I need to track the historical state of tickets of a project through a date range. The date range is determined by a project manager (in this case it's January 1st through January 9th).
For each ticket, I have the following set of historical data. Each time something changes in the ticket (state, description, assignee, customer update, and other attributes not shown in this problem), a "timestamp" entry is made in the database.
ticket_num status_changed_date from_state to_state
123456 2011-01-01 18:03:44 -- 1
123456 2011-01-01 18:10:26 1 2
123456 2011-01-01 14:37:10 2 2
123456 2011-01-02 07:55:44 2 3
123456 2011-01-03 06:12:18 3 2
123456 2011-01-04 19:03:43 3 3
123456 2011-01-05 02:05:24 3 4
123456 2011-01-06 18:13:28 4 4
123456 2011-01-07 13:14:48 4 5
123456 2011-01-09 01:35:39 5 5
How can I query the database for a given time (determined by my script) and find out what state each of the tickets are in?
For example: To produce the chart shown above, given the date 2011-01-02 12:00:00, how many tickets were in the state "2"?
I've tried querying the database with specific dates and ranges, but can't figure out the proper way to get the data to create the chart. Thanks in advance for any help.
I'm not exactly sure I know what you want. But . . .
Assuming a table definition like:
create table ticket_data (ticket_num int,
status_changed_date datetime,
from_state int,
to_state int);
The following, for example would give you the number of values per day:
select date(status_changed_date) as status_date, count(*)
from ticket_data
group by status_date;
Now, if you want just from_state = 2, just add a where clause in to that effect. If you want just the ones on Jan 2, then add in where date(status_changed_date) = '2011-01-02'
Or, if you you're looking for the distinct number of tickets per day then, change count(*) to count(distinct ticket_num)
Is this what you're asking? SQL Fiddle here
Ok so if you are trying to get a count of records in a certain state at a certain time, I think a stored proc might be necessary.
CREATE PROCEDURE spStatesAtDate
#Date datetime,
#StateId int
AS
BEGIN
SET NOCOUNT ON;
SELECT COUNT(*) as Count
FROM ticket_table t1
WHERE to_state = #StateId AND status_changed_date < #Date
AND status_changed_date = (SELECT MAX(status_changed_date) FROM ticket_table t2 where t2.ticket_num=t1.ticket_num AND status_changed_date < #Date)
END
then to call this for the above example, you're query would look like
EXEC spStatesAtDate #Date='2011-01-02 12:00:00', #StateId=2
You can use a subquery to select the last modification date before a given point grouped by ticket_num and then select the states at this time.
SELECT
ticket_num,
to_state,
status_changed_date
FROM
tickets
WHERE
status_changed_date IN (
SELECT MAX(status_changed_date)
FROM tickets
WHERE status_changed_date < '2012-02-01 01:00:00'
GROUP BY ticket_num
)
It all boils down to common question: how to get list of items and their most recent statuses. So. Given one issue, we can get its most recent status with query:
select to_state
from ticket_states
where ticket_num = t.ticket_num
order by status_changed_date desc
limit 1
Next, we need to get all applicable distinct issue ids, which is a simple distinct select:
select distinct ticket_num from ticket_states
With these two subqueries we can already start building. For example, current list of issues and their latest statuses before specified date would be:
select t.ticket_num
, (select to_state
from ticket_states
where ticket_num = t.ticket_num
and status_changed_date <= '2012-01-01'
order by status_changed_date desc
limit 1) as last_state
from (select distinct ticket_num
from ticket_states) t;
All issues, which were non-existant at at the specified time will have last_state set to null.
This probably isn't the best way of doing this, but it is first which came to mind. I'll leave other stuff to you. Also I should mention that this is not a very efficient solution also.