Can anyone kindly point out how to group data until today (for last 5 years) for Indian fiscal (Apr-Mar). Say for example I need to extract 'field1','field2' from table 'aaa' from 01-Apr to today date for the last 5 years. My current solution can work safe until Dec, but later will run into error
SELECT
"Date",
"Daily data",
"ID",
"GA%",
"MA%"
FROM "table"
WHERE month("Date") >= 4
AND month("Date") <= month(today())
AND date("Date") < date(today())
Expected result format grouped by fiscal years:
FY-1 sum(daily data during the period) sum(GA) sum(MA)
FY-2 sum(daily data during the period) sum(GA) sum(MA)
SELECT
"Date",
"Daily data",
"ID",
"GA%",
"MA%"
FROM "table"
WHERE
"Date" between '2021-04-01' and '2021-11-29'
OR
"Date" between '2020-04-01' and '2020-11-29'
OR
"Date" between '2019-04-01' and '2019-11-29'
OR
"Date" between '2018-04-01' and '2018-11-29'
OR
"Date" between '2017-04-01' and '2017-11-29'
untested notepad scribble
SELECT
MIN(`Date`) AS StartDate
, MAX(`Date`) AS EndDate
, COUNT(ID) AS CountId
, SUM(`GA%`) AS `TotalGa%`
, SUM(`MA%`) AS `TotalMa%`
FROM `table` AS aaa
WHERE
(
(YEAR(`Date`) BETWEEN YEAR(CURRENT_DATE) - 4 AND YEAR(CURRENT_DATE) - 1)
OR
(YEAR(`Date`) = YEAR(CURRENT_DATE) AND MONTH(`Date`) <= 11)
OR
(YEAR(`Date`) = YEAR(CURRENT_DATE) - 5 AND MONTH(`Date`) > 3)
)
AND
(
MONTH(`Date`) NOT IN (12, 1, 2, 3)
OR
YEAR(`Date`) = YEAR(CURRENT_DATE)
)
GROUP BY CASE WHEN MONTH(`Date`) <= 3 THEN YEAR(`Date`) - 1
ELSE YEAR(`Date`) END
ORDER BY MIN(`Date`) DESC
SELECT '2017-05-30' AS `short_date`,
'Stats' AS `group`,
'Active ' AS `subgroup`,
'' AS `row`,
CASE
WHEN COUNT(DISTINCT(guild_name)) >= 1 AND COUNT(DISTINCT(guild_name)) <= 5 THEN '1 - 5 '
WHEN COUNT(DISTINCT(guild_name)) >= 6 AND COUNT(DISTINCT(guild_name)) <= 10 THEN '6 - 10 '
WHEN COUNT(DISTINCT(guild_name)) >= 11 AND COUNT(DISTINCT(guild_name)) <= 15 THEN '11 - 15 '
WHEN COUNT(DISTINCT(guild_name)) >= 16 AND COUNT(DISTINCT(guild_name)) <= 20 THEN '16 - 20 '
WHEN COUNT(DISTINCT(guild_name)) >= 21 AND COUNT(DISTINCT(guild_name)) <= 25 THEN '21 - 25 '
WHEN COUNT(DISTINCT(guild_name)) >= 30 THEN '> 30' END AS `value`
FROM table
WHERE guild_name !=0
GROUP BY
`short_date`,
`group`,
`subgroup`
How not to count a value in each case, how to count it once and use in each case?
How about you move the count to a subquery and move the case outside like this:
select `short_date`, `group`, `subgroup`, `row`,
CASE
WHEN nb_guild >= 1 AND nb_guild <= 5 THEN '1 - 5 '
WHEN nb_guild >= 6 AND nb_guild <= 10 THEN '6 - 10 '
WHEN nb_guild >= 11 AND nb_guild <= 15 THEN '11 - 15 '
WHEN nb_guild >= 16 AND nb_guild <= 20 THEN '16 - 20 '
WHEN nb_guild >= 21 AND nb_guild <= 25 THEN '21 - 25 '
WHEN nb_guild >= 30 THEN '> 30'
END AS `value`
from
(
SELECT '2017-05-30' AS `short_date`,
'Stats' AS `group`,
'Active ' AS `subgroup`,
'' AS `row`,
COUNT(DISTINCT(guild_name)) as nb_guild
FROM table
WHERE guild_name !=0
GROUP BY
`short_date`,
`group`,
`subgroup`
) as subquery
This way your count only gets executed once in the subquery and your outer query does its treatment on the resulting resultset.
The data is stored in DB in UTC , I have to convert local to UTC fetch it then show result in local time .
Now I am from India so if I want to search the data for today I have to query from 22nd March 6:30 PM UTC to 23rd March 6:30 PM UTC . Now Say I want to check data for every day of week until now which is 4:30 PM local . Now I wrote this query [ In simple words my objective is to get visitor number of each day from 12 AM to 4:30 PM ]
SELECT
FLOOR(TIMESTAMPDIFF(HOUR, "2017-03-16 18:29:59",
visit.date_created)/24) as dayofweek,
DAYOFWEEK(visit.date_created) day_num,
#rownum := #rownum + 1 as date_created_set_av,
count(distinct(visit.pkey)) AS Visits,
sum(revenue) AS Revenue,
sum(revenue) / count(distinct(visit.pkey)) as EPC
FROM la_20.visit, la_20.action
cross join (select #rownum := 0) r
WHERE visit.pkey=action.pkey and (visit.is_bot = 0)
AND visit.date_created >="2017-03-16 18:29:59"
AND visit.date_created <="2017-03-23 18:29:59"
AND TIME(visit.date_created)<="16:30:00"
GROUP BY dayofweek order by day_num
but what it does is fetch the value from 2017-03-23 00:00:00 to 2017-03-23 16:30:00 . What I need is to show result of 16th to 23rd everyday's data from 18:29:59 to 16:30:00. Remember I need the result of everyday's not one day's. Can anyone help
You should change your WHERE clause into
WHERE visit.pkey=action.pkey and (visit.is_bot = 0)
AND visit.date_created >="2017-03-22 18:29:59" and visit.date_created <="2017-03-23 14:29:59"
UPDATED
Today midnight: DATEADD(d,0,DATEDIFF(d,0,GETDATE()))
Today 4pm: DATEADD(HOUR, 16, DATEADD(d,0,DATEDIFF(d,0,GETDATE())))
WHERE visit.pkey=action.pkey and (visit.is_bot = 0)
AND visit.date_created >= DATEADD(d,0,DATEDIFF(d,0,GETDATE())) and visit.date_created <= DATEADD(HOUR, 16, DATEADD(d,0,DATEDIFF(d,0,GETDATE())))
Update 2:
Then you'll have to expand your where clause like this I guess.
WHERE visit.pkey=action.pkey and (visit.is_bot = 0)
AND (
(visit.date_created >= DATEADD(d, 0,DATEDIFF(d,0,GETDATE())) and visit.date_created <= DATEADD(HOUR, 16, DATEADD(d, 0,DATEDIFF(d,0,GETDATE()))))
OR (visit.date_created >= DATEADD(d,-1,DATEDIFF(d,0,GETDATE())) and visit.date_created <= DATEADD(HOUR, 16, DATEADD(d,-1,DATEDIFF(d,0,GETDATE()))))
OR (visit.date_created >= DATEADD(d,-2,DATEDIFF(d,0,GETDATE())) and visit.date_created <= DATEADD(HOUR, 16, DATEADD(d,-2,DATEDIFF(d,0,GETDATE()))))
OR (visit.date_created >= DATEADD(d,-3,DATEDIFF(d,0,GETDATE())) and visit.date_created <= DATEADD(HOUR, 16, DATEADD(d,-3,DATEDIFF(d,0,GETDATE()))))
OR (visit.date_created >= DATEADD(d,-4,DATEDIFF(d,0,GETDATE())) and visit.date_created <= DATEADD(HOUR, 16, DATEADD(d,-4,DATEDIFF(d,0,GETDATE()))))
OR (visit.date_created >= DATEADD(d,-5,DATEDIFF(d,0,GETDATE())) and visit.date_created <= DATEADD(HOUR, 16, DATEADD(d,-5,DATEDIFF(d,0,GETDATE()))))
OR (visit.date_created >= DATEADD(d,-6,DATEDIFF(d,0,GETDATE())) and visit.date_created <= DATEADD(HOUR, 16, DATEADD(d,-6,DATEDIFF(d,0,GETDATE()))))
)
Have you tried the following where clause instead?
WHERE visit.pkey=action.pkey and (visit.is_bot = 0)
AND visit.date_created >="2017-03-22 18:29:59"
AND visit.date_created <="2017-03-23 14:29:59"
3. Edit
OK, since OP wants something different again - and why not ;-) - here is another solution that might (or might not) solve his problem:
SELECT
COUNT( CASE WHEN d between
adddate(curdate(), interval -7 day) AND addtime(adddate(curdate(), interval -7 day),'16:00:00')
THEN 1 END ) dm7,
COUNT( CASE WHEN d between
adddate(curdate(), interval -6 day) AND addtime(adddate(curdate(), interval -6 day),'16:00:00')
THEN 1 END ) dm6,
COUNT( CASE WHEN d between
adddate(curdate(), interval -5 day) AND addtime(adddate(curdate(), interval -5 day),'16:00:00')
THEN 1 END ) dm5,
COUNT( CASE WHEN d between
adddate(curdate(), interval -4 day) AND addtime(adddate(curdate(), interval -4 day),'16:00:00')
THEN 1 END ) dm4,
COUNT( CASE WHEN d between
adddate(curdate(), interval -3 day) AND addtime(adddate(curdate(), interval -3 day),'16:00:00')
THEN 1 END ) dm3,
COUNT( CASE WHEN d between
adddate(curdate(), interval -2 day) AND addtime(adddate(curdate(), interval -2 day),'16:00:00')
THEN 1 END ) dm2,
COUNT( CASE WHEN d between
adddate(curdate(), interval -1 day) AND addtime(adddate(curdate(), interval -1 day),'16:00:00')
THEN 1 END ) dm1,
COUNT( CASE WHEN d between
curdate() AND addtime( curdate() ,'16:00:00')
THEN 1 END ) today
FROM (select '2017-03-17 15:00:01' d
union all select '2017-03-19 14:00:01'
union all select '2017-03-19 12:00:01'
union all select '2017-03-19 13:00:01'
union all select '2017-03-19 11:00:01'
union all select '2017-03-20 11:20:01'
union all select '2017-03-20 11:30:01'
union all select '2017-03-20 10:40:01'
union all select '2017-03-20 10:23:01' ) dates
This is an isolated query that works directly on the sample data given in the subquery. It results in the following list ("dm1"=day minus 1):
dm7 | dm6 | dm5 | dm4 | dm3 | dm2 | dm1 | today
1 | 0 | 4 | 4 | 0 | 0 | 0 | 0
You can test it here: http://rextester.com/ITLBL24540
I have two tables
1) outreach
id profile_id url
-------------------------
1 2 www.test.com
2 3 www.google.com
3 4 www.example.com
4 2 www.test2.com
5 2 www.test3.com
6 2 www.test4.com
2). outreach_links
id outreach_id start_date created_at cost status
-----------------------------------------------------------------------
1 1 2016-12-01 00:00:00 2016-12-07 00:00:00 100.00 Approved
2 1 2016-12-02 00:00:00 2016-12-09 00:00:00 120.00 Approved
3 1 NUll 2016-12-28 00:00:00 20.00 Pending
4 1 2016-12-05 00:00:00 2016-12-10 00:00:00 35.00 Approved
5 1 2016-12-07 00:00:00 2016-12-13 00:00:00 10.00 Approved
6 2 2016-12-10 00:00:00 2016-12-15 00:00:00 10.00 Pending
7 2 2016-12-13 00:00:00 2016-12-18 00:00:00 10.00 Approved
8 2 2016-12-01 00:00:00 2016-12-28 00:00:00 10.00 Pending
9 2 2016-12-04 00:00:00 2016-12-21 00:00:00 10.00 Approved
10 2 2016-12-09 00:00:00 2016-12-22 00:00:00 15.00 Pending
I am trying to do a count by Month/Year and I thought its working but I think its not working because of "profile_id" issue here is my query:
select monthname(date) as Month, year(date) as Year, month(date) as Mn, UNIX_TIMESTAMP(CONCAT(year(date),"-",month(date),"-","01")) as tt,
(select count(*) from outreach_links where year(outreach_links.created_at) = year and month(outreach_links.created_at) = month and status = "Pending" and created_at>="2016-12-01 00:00:00" and created_at<="2016-12-31 00:00:00") as pp,
(select count(*) from outreach_links where year(outreach_links.start_date) = year and month(outreach_links.start_date) = month and status = "Approved" and start_date>="2016-12-01 00:00:00" and start_date<="2016-12-31 00:00:00") as aa,
(select sum(cost) from outreach_links where year(outreach_links.start_date) = year and month(outreach_links.start_date) = month and status = "Approved" and start_date>="2016-12-01 00:00:00" and start_date<="2016-12-31 00:00:00") as cc
from
(select year(outreach_links.created_at) as year, month(outreach_links.created_at) as month, outreach_links.created_at as date
from outreach_links
inner join outreach on outreach.id = outreach_links.outreach_id
where outreach_links.created_at>="2016-12-01 00:00:00" and outreach_links.created_at<="2016-12-31 00:00:00" and outreach.profile_id=2
union
select year(outreach_links.start_date) as year, month(outreach_links.start_date) as month, outreach_links.start_date as date
from outreach_links
inner join outreach on outreach.id = outreach_id
where start_date>="2016-12-01 00:00:00" and start_date<="2016-12-31 00:00:00" and outreach.profile_id=2 ) t1
group by year, month
order by date
So I am doing a date range from "2016-12-01 00:00:00" to "2016-12-31 00:00:00" these could be any date range inputed by the user , and try to do a count based on outreach.profile_id = 2 , my output is wrong its counting everything for all profile_ids, I am not sure why
Note: this is just a sample of the tables , there might be more records and the user inputed Date range from to could be different , I want to group them by Month / Year
here is my output: ( its counting ALL records)
array:1 [▼
0 => {#394 ▼
+"Month": "December"
+"Year": "2016"
+"Mn": "12"
+"tt": "1480568400.000000"
+"pp": "4"
+"aa": "6"
+"cc": "285.00"
}
]
Which is wrong it should count only for profile_id=2 , here is the DESIRED output I want:
array:1 [▼
0 => {#394 ▼
+"Month": "December"
+"Year": "2016"
+"Mn": "12"
+"tt": "1480568400.000000"
+"pp": "1"
+"aa": "4"
+"cc": "265.00"
}
]
As you can see the 3 counts are wrong they suppose to be:
"pp": "1"
"aa": "4"
"cc": "265.00"
here is what I am looking for:
1). **"pp" is Total Pending** Count when status="Pending" based on created_at
2). **"aa" is Total Approved** Count when status="Approved" based on start_date
3). **"cc" is Total Cost** Sum of All cost when Status="Approved" and based on start_date
4). Group by Month & Year of the user imputed Date Range
here is a SQLFIDDLE >> http://sqlfiddle.com/#!9/87dfa8/1
can you please help me fix it?
Thanks
I think you want something like this:
SELECT MONTHNAME(d.date) AS Month
, YEAR(d.date) AS Year
, MONTH(d.date) AS Mn
, SUM(IF(l.status = 'Pending' AND l.created_at >= d.date AND l.created_at < d.date + INTERVAL 1 MONTH ,1 ,0)) AS pp
, SUM(IF(l.status = 'Approved' AND l.start_date >= d.date AND l.start_date < d.date + INTERVAL 1 MONTH ,1 ,0)) AS aa
, SUM(IF(l.status = 'Approved' AND l.start_date >= d.date AND l.start_date < d.date + INTERVAL 1 MONTH ,l.cost,0)) AS cc
FROM ( SELECT '2016-12-01' + INTERVAL 0 MONTH AS date ) d
JOIN outreach o
ON o.profile_id = 2
LEFT
JOIN outreach_links l
ON l.outreach_id = o.id
AND ( ( l.start_date >= d.date + INTERVAL 0 MONTH
AND l.start_date < d.date + INTERVAL 1 MONTH
)
OR ( l.created_at >= d.date + INTERVAL 0 MONTH
AND l.created_at < d.date + INTERVAL 1 MONTH
)
)
GROUP BY d.date
EDIT
To specify the end date of the range along with the start date, the inline view d can return two date values. And the outer query can reference the second date value, in this example d.end_date, as well as the start of the range d.date.
SELECT MONTHNAME(d.date) AS Month
, YEAR(d.date) AS Year
, MONTH(d.date) AS Mn
, SUM(IF(l.status = 'Pending' AND l.created_at >= d.date AND l.created_at < d.end_date,1 ,0)) AS pp
, SUM(IF(l.status = 'Approved' AND l.start_date >= d.date AND l.start_date < d.end_date,1 ,0)) AS aa
, SUM(IF(l.status = 'Approved' AND l.start_date >= d.date AND l.start_date < d.end_date,l.cost,0)) AS cc
FROM ( SELECT '2016-12-01' + INTERVAL 0 MONTH AS date
, '2016-12-16' + INTERVAL 0 MONTH AS end_date
) d
JOIN outreach o
ON o.profile_id = 2
LEFT
JOIN outreach_links l
ON l.outreach_id = o.id
AND ( ( l.start_date >= d.date
AND l.start_date < d.end_date
)
OR ( l.created_at >= d.date
AND l.created_at < d.end_date
)
)
GROUP BY d.date, d.end_date
I have query like this :
SELECT EXTRACT(MONTH FROM d.mydate) AS synmonth, SUM(apcp) AS apcptot
FROM t_synop_data2 d
WHERE d.mydate
BETWEEN '2011-01-01' AND '2011-12-31'
AND d.idx_synop = '06712'
GROUP BY synmonth
This query adds all rain (apcp) in a month like this :
1 32.8 => from 2011.01.01 to 2011.01.31
2 27.2 => from 2011.02.01 to 2011.02.28
3 21.0
4 21.8
5 88.5
6 131.4
7 118.6
8 57.1
9 80.9
10 84.6
11 1.1
12 143.5 => from 2011.12.01 to 2011.12.31
That's what I want, but with a little difference.
This difference is that i have to adds apcp from day 2 in the month to day 1 next month and then return a result like above.
1 132.8 => from 2011.01.02 to 2011.02.01
2 27.2 => from 2011.02.02 to 2011.03.01
3 21.0
4 21.8
5 88.5
6 131.4
7 118.6
8 57.1
9 80.9
10 84.6
11 1.1
12 143.5 => from 2011.12.02 to 2012.01.01
I tried something with add_date(), extract() or date_format() but without result.
Thank you for your answer
Vince
Here is the query :
SELECT EXTRACT(MONTH FROM ADDDATE(d.mydate,-1) ) AS synmonth
, SUM(apcp) AS apcptot
FROM t_synop_data2 AS d
WHERE ADDDATE(d.mydate,-1) BETWEEN '2011-01-01' AND '2012-12-31'
AND d.idx_synop = '06712'
GROUP BY synmonth
You can check the result by adding two columns like this:
SELECT EXTRACT(MONTH FROM ADDDATE(d.mydate,-1) ) AS synmonth
, SUM(apcp) AS apcptot
, MIN(d.mydate) AS date_min
, MAX(d.mydate) AS date_max
FROM t_synop_data2 AS d
WHERE ADDDATE(d.mydate,-1) BETWEEN '2011-01-01' AND '2012-12-31'
AND d.idx_synop = '06712'
GROUP BY synmonth
You can group by EXTRACT(MONTH FROM d.mydate - INTERVAL 1 DAY)
SELECT EXTRACT(MONTH FROM d.mydate) AS synmonth, SUM(apcp) AS apcptot
FROM t_synop_data2 d
WHERE d.mydate
BETWEEN '2011-01-01' AND '2011-12-31'
AND d.idx_synop = '06712'
GROUP BY EXTRACT(MONTH FROM d.mydate - INTERVAL 1 DAY)