getting multi row data into columns in mysql - mysql

SELECT
Day,
month,
year,
GROUP_CONCAT(total),
GROUP_CONCAT(SP_ID)
FROM
(
SELECT
DATE_FORMAT(l.act_date, '%d') AS DAY,
DATE_FORMAT(l.act_date, '%M') AS MONTH,
EXTRACT(YEAR FROM l.act_date) AS YEAR,
COUNT(*) as total,l.sp_id
FROM lead_activity2 as l
right outer join salesperson as s on l.sp_id=s.sp_id
WHERE l.act_name='scb'
AND ((l.act_date>='2012-09-07 13:03:27' )
AND (l.act_date<= '2012-11-07 13:03:27'))
GROUP BY MONTH, YEAR, DAY, l.sp_id
ORDER BY YEAR DESC, MONTH DESC, DAY DESC, l.sp_id DESC
) t GROUP BY day, month, year
http://sqlfiddle.com/#!2/1514d/3 - you can view the scheme and the query,
what i would like to get is
18 | october | 2012 | 0,0,1,1 | 6,5,4,3
spid 6 and spid 5 have no data for 18 october but still should be shown tried doing right join and right outer join both dont seem to work...

Use GROUP_CONCAT like so:
SELECT
Day,
month,
year,
GROUP_CONCAT(total),
GROUP_CONCAT(SP_ID)
FROM
(
SELECT
DATE_FORMAT(l.act_date, '%d') AS DAY,
DATE_FORMAT(l.act_date, '%M') AS MONTH,
EXTRACT(YEAR FROM l.act_date) AS YEAR,
COUNT(*) as total,l.sp_id
FROM lead_activity2 as l
WHERE l.act_name='scb'
AND ((l.act_date>='2012-09-07 13:03:27' )
AND (l.act_date<= '2012-11-07 13:03:27'))
GROUP BY MONTH, YEAR, DAY, l.sp_id
ORDER BY YEAR DESC, MONTH DESC, DAY DESC, l.sp_id DESC
) t GROUP BY day, month, year
Updated SQL Fiddle
Update: Yes you can do this, but use LEFT JOIN to include non matching sp_id. These non matching ids will have a value of NULL use IFNULL to display it with zeros like so:
SELECT
Day,
month,
year,
GROUP_CONCAT(total) Total,
GROUP_CONCAT(SP_ID) 'List of sp_ids'
FROM
(
SELECT
DATE_FORMAT(l.act_date, '%d') AS DAY,
DATE_FORMAT(l.act_date, '%M') AS MONTH,
EXTRACT(YEAR FROM l.act_date) AS YEAR,
COUNT(*) as total,
IFNULL(s.sp_id , 0) sp_id
FROM lead_activity2 as l
LEFT JOIN salesperson s ON l.sp_id = s.sp_id
WHERE l.act_name='scb'
AND ((l.act_date>='2012-09-07 13:03:27' )
AND (l.act_date<= '2012-11-07 13:03:27'))
GROUP BY MONTH, YEAR,DAY,s.sp_id
) t
ORDER BY YEAR DESC,
MONTH DESC,
DAY DESC,
sp_id DESC
Updates SQL Fiddle Demo

Related

SQL: Getting null values on comparing current values to previous period

I have copied this SQL query from another website and I'm not actually sure why it returns null values for the previous period and the month comparing it with. What should I adjust in the query to get the desired result?
SQL Query:
WITH monthly_metrics AS (
SELECT EXTRACT(year from day) as year,
EXTRACT(month from day) as month,
SUM(revenue) as revenue
FROM daily_metrics
GROUP BY 1,2
)
SELECT year AS current_year,
month AS current_month,
revenue AS revenue_current_month,
LAG(year,12) OVER ( ORDER BY year, month) AS previous_year,
LAG(month,12) OVER ( ORDER BY year, month) AS month_comparing_with,
LAG(revenue,12) OVER ( ORDER BY year, month) AS revenue_12_months_ago,
revenue - LAG(revenue,12) OVER (ORDER BY year, month) AS month_to_month_difference
FROM monthly_metrics
ORDER BY 1,2;
Query Result:
dbfiddle

Can I get every month of the year even if there is not data for that month in DB

I want to get a statistic for every month of the years i have in DB
SELECT monthname(created_at) AS month, YEAR(created_at) AS year, count(*) AS number
FROM tableName
WHERE type_of_user = "someType"
GROUP BY year, month(created_at)
ORDER BY created_at DESC
Now it gives me only month that I have, but I need to get statistics for every month, even if I don't have any stored data for that month
Create a calendar table. This will need one entry per month, for every year that you intend to use.
Then select from the calendar table, and join in the values that you get from your current query. Use COALESCE() to put a zero-value where the entry is NULL (e.g. when there are no records in the tableName for that month and year).
SELECT MONTHNAME(date) as month,
YEAR(date) as year,
COALESCE(number, 0) as number
FROM calendar AS C
LEFT JOIN (
SELECT created_at, COUNT(*) as number
FROM tableName AS T
WHERE T.type_of_user = 'someType'
GROUP BY YEAR(created_at), MONTH(created_at)
) AS T
ON MONTH(T.created_at) = MONTH(C.date) AND YEAR(T.created_at) = YEAR(C.date)
GROUP BY month, YEAR(created_at)
ORDER BY MONTH(date), YEAR(date)
SQL fiddle at http://sqlfiddle.com/#!9/e0a4dc/
SELECT month(created_at) as month
FROM tableName
RIGHT JOIN (select row_number() over (order by 1) as i
from someTableWithMoreThan12Records limit 12) x
ON x.i=month(created_at)
ORDER BY I;
JOINing with a table that has all the records will give you every month.

MySQL Rolling Count of Rows

I'm trying to do a rolling count of registration growth on a student website.
The query looks as follows:
SELECT COUNT(type) as student_count, MONTH(created_at) as month, YEAR(created_at) as year
FROM users
WHERE type = 'student'
GROUP BY MONTH(created_at), YEAR(created_at)
ORDER BY year, month
This produces the following output:
What I'm trying to achieve in the query is to keep adding up the student_counts from the previous rows.
So:
December 2014 should have 15 students
January 2015 should have 16 students
February 2015 should have 34 students
and so on...
Is this possible in SQL or is it better to do this when outputting the data in the code itself?
select *, #sum := #sum + student_count as sum
from
(
SELECT YEAR(created_at) as year,
MONTH(created_at) as month,
COUNT(type) as student_count
FROM users
WHERE type = 'student'
GROUP BY year, month
ORDER BY year, month
) tmp
CROSS JOIN (select #sum := 0) s
Try using with rollup
SELECT COUNT(type) as student_count, MONTH(created_at) as month, YEAR(created_at) as year
FROM users
WHERE type = 'student'
GROUP BY YEAR(created_at), MONTH(created_at) WITH ROLLUP
Try this:
SELECT #cumulative := 0;
SELECT #cumulative := #cumulative + student_count student_count,
month, year
FROM (
SELECT COUNT(type) as student_count,
MONTH(created_at) as month,
YEAR(created_at) as year
FROM users
WHERE type = 'student'
GROUP BY MONTH(created_at), YEAR(created_at)
) A ORDER BY year, month
One approach to handle this in MySQL uses a correlated subquery to find the running total.
SELECT DISTINCT
(SELECT COUNT(*) FROM users u2
WHERE DATE_FORMAT(u2.created_at, '%Y-%m') <=
DATE_FORMAT(u1.created_at, '%Y-%m')) AS student_count,
DATE_FORMAT(created_at, '%Y-%m') AS ym
FROM users u1
WHERE type = 'student'
ORDER BY DATE_FORMAT(created_at, '%Y-%m');
Demo
Not much to explain here, except that SELECT DISTINCT gives us each unique year-month value in the table as a single record. We then count all rows at that point in time or earlier to find the running total.

Mysql count columns values based on condition

I have a table with columns day, month, year, total_payments. And I have to calculate total_payments according to days, months, years.
How can I calculate values?
I am thinking code like :
select
month, year, sum(total_payments)
from
webassignment.subscription_stats
group by
day;
select
month, year, sum(total_payments)
from
webassignment.subscription_stats
group by
month;
select
month, year, sum(total_payments)
from
webassignment.subscription_stats
group by
year;
but it will not return the correct answers. And I want to calculate total_payments daywise, monthwise, yearwise. Please help me to find values.
Sample input :
Day Month Year Total_payments
10 01 2008 10
10 01 2008 20
11 02 2008 10
10 03 2010 10
Output:
Daywise :
day month year total_payments
-----------------------------
10 01 2008 30
11 02 2008 10
10 03 2010 10
Same for month and yearwise
You can get a summary with Totals by Year, Month and Day using GROUP BY WITH ROLLUP:
SELECT
`Year`,
`Month`,
`Day`,
SUM(`Total_payments`) as `Totals`
FROM `webassignment`.`subscription_stats`
GROUP BY `Year`,`Month`,`Day` WITH ROLLUP;
If you want individual queries for Year, Month and Day:
By Year:
SELECT
`Year`,
SUM(`Total_payments`) as `Totals`
FROM `webassignment`.`subscription_stats`
GROUP BY `Year`
ORDER BY `Year;
By Month:
SELECT
`Year`,
`Month`,
SUM(`Total_payments`) as `Totals`
FROM `webassignment`.`subscription_stats`
WHERE `Year` = 2017
GROUP BY `Year`,`Month`
ORDER BY `Year`,`Month`;
By Day:
SELECT
`Year`,
`Month`,
`Day`,
SUM(`Total_payments`) as `Totals`
FROM `webassignment`.`subscription_stats`
GROUP BY `Year`,`Month`,`Day`
ORDER BY `Year`,`Month`,`Day`;
A way could be the use on an union for show the different result based on different group by level
select day, month,year,sum(total_payments)
from webassignment.subscription_stats group by day, month,year
union
select null, month,year,sum(total_payments)
from webassignment.subscription_stats group by month,year
union
select null, null ,year,sum(total_payments)
from webassignment.subscription_stats group by year
order by year, month, day
for the sample you provided should be enough
select day, month,year,sum(total_payments)
from webassignment.subscription_stats group by day, month,year
order by day, month,year

MySQL month over month totals compared to previous month

I'd like to sum the amount column for a given month, as well as the total for the previous month. Right now the first month's total works, but every month thereafter is too high by at least 2 order of magnitude.
SELECT month, year, total, previous_month, previous_year, previous_total FROM (
SELECT MONTH(p1.start_date) AS month,
YEAR(p1.start_date) AS year,
SUM(p1.amount) AS total,
SUM(p2.amount) AS previous_total,
MONTH(DATE_SUB(p1.start_date, INTERVAL 1 MONTH)) AS previous_month,
YEAR(DATE_SUB(p1.start_date, INTERVAL 1 MONTH)) AS previous_year
FROM trackings p1
LEFT JOIN trackings p2 ON EXTRACT(YEAR_MONTH FROM DATE_SUB(p1.start_date, INTERVAL 1 MONTH)) = EXTRACT(YEAR_MONTH FROM p2.start_date)
GROUP BY EXTRACT(YEAR_MONTH FROM p1.start_date)
) AS p3;
Related question: I'm doing the same DATE_SUB 3 times. Is there a way to clean up the date related parts to be more efficient?
Sample: http://sqlfiddle.com/#!2/3013a/1
Think the problem is you are getting rows counted multiple times on the join. Ie, you have a sum of all the amounts for a month, but each row from that month is being joined with all rows for the previous month.
Solution using a couple of subselect:-
SELECT ThisMonth.MONTH, ThisMonth.YEAR, ThisMonth.TOTAL, PrevMonth.MONTH AS PREVIOUS_MONTH, PrevMonth.YEAR AS PREVIOUS_YEAR, PrevMonth.TOTAL AS PREVIOUS_TOTAL
FROM
(
SELECT MONTH(start_date) AS `month`,
YEAR(start_date) AS `year`,
EXTRACT(YEAR_MONTH FROM start_date) AS YearMonth,
SUM(amount) AS total
FROM trackings
GROUP BY `month`, `year`, YearMonth
) ThisMonth
LEFT OUTER JOIN
(
SELECT MONTH(start_date) AS `month`,
YEAR(start_date) AS `year`,
EXTRACT(YEAR_MONTH FROM DATE_ADD(start_date, INTERVAL 1 MONTH)) AS YearMonth,
SUM(amount) AS total
FROM trackings
GROUP BY `month`, `year`, YearMonth
) PrevMonth
ON ThisMonth.YearMonth = PrevMonth.YearMonth