SQL Sum and Count Separated by Month - sql

I am writing a script that query's a table and counts all rows that have a status of 10 and separates the total count by month. Something is
not right considering I have two Decembers in my results.
In November, there is only one date in it meaning two rows have a status of 10 and are under the same date (11-04). December has 252 rows on the same date (12-04) and 1 row with a 12-05 date .
How to query and separate a count and date by months?
Any help is most appreciated.
SELECT CONVERT(CHAR(3), Datename(month, datecomplete)) AS Month,
Count(*) AS Val
FROM nwds
WHERE status = 10
GROUP BY Datediff(month, 0, datecomplete),
datecomplete
My Results
Nov 2
Dec 252
Dec 1
Desired Results
Nov 2
Dec 253

SELECT LEFT(DATENAME(M, datecomplete), 3) AS Month,
Count(*) AS Val
FROM nwds
WHERE status = 10
GROUP BY LEFT(DATENAME(M, datecomplete), 3)
If you have ever get data for different years, you can add the year to the GROUP BY.
SELECT LEFT(DATENAME(M, datecomplete), 3) AS Month,
YEAR(datecomplete) AS Year,
Count(*) AS Val
FROM nwds
WHERE status = 10
GROUP BY LEFT(DATENAME(M, datecomplete), 3), YEAR(datecomplete)

datecomplete should be excluded from group by, or the results would be grouped by day. Grouping needs to be on month and year part of datecomplete column.
SELECT
CONVERT(CHAR(3), Datename(month, datecomplete)) AS Month,
count(*) AS Val
FROM nwds
WHERE status = 10
GROUP BY CONVERT(CHAR(3), Datename(month, datecomplete)) ,
datepart(yyyy, datecomplete)

Try this
select CONVERT(char(3),DATENAME(MONTH,datecomplete)) as [month],
count(*) as val
from nwds
WHERE status = 10
group by CONVERT(char(3),DATENAME(MONTH,datecomplete))

Related

Remove Duplicates and show Total sales by year and month

i am trying to work with this query to produce a list of all 11 years and 12 months within the years with the sales data for each month. Any suggestions? this is my query so far.
SELECT
distinct(extract(year from date)) as year
, sum(sale_dollars) as year_sales
from `project-1-349215.Dataset.sales`
group by date
it just creates a long list of over 2000 results when i am expecting 132 max one for each month in the years.
You should change your group by statement if you have more results than you expected.
You can try:
group by YEAR(date), MONTH(date)
or
group by EXTRACT(YEAR_MONTH FROM date)
A Grouping function is for takes a subsection of the date in your case year and moth and collect all rows that fit, and sum it up,
So a sĀ“GROUp BY date makes no sense, what so ever as you don't want the sum of every day
So make this
SELECT
extract(year from date) as year
,extract(MONTH from date) as month
, sum(sale_dollars) as year_sales
from `project-1-349215.Dataset.sales`
group by 1,2
Or you can combine both year and month
SELECT
extract(YEAR_MONTH from date) as year
, sum(sale_dollars) as year_sales
from `project-1-349215.Dataset.sales`
group by 1

Count number of members each month

I have a table like so
--Member--
ID char(10),
Name (nvarchar(50),
joiningDay date,
exitDay date
How can I count total number of member each month with a selected period of time with member that has exit will not be counted in that month
and the result should be like:
Start from month 1 to month 10
Month totalOfMember
1 5
2 6
3 9
... ...
10 35
If you want to select number of members joined in a month
select month(joiningday)[Month],sum(case when month(joiningday)=month(exitday) then 0 else 1 end)TotalOfMember
from Member where joiningDay>='1 jan 2020' and joiningDay<'1 jan 2021'
group by month(joiningday)
order by [Month]
But I would suggest to use Format(datevalue,'yyyy MM') to count member month and year wise instead of only month. 01 can be repeated in a date range if there are two January but 2020 01 and 2021 01 will be uniquely identified.
select Format(joiningday,'yyyy MM') [Month],sum(case when Format(joiningday,'yyyy MM') = Format(exitday,'yyyy MM') then 0 else 1 end)TotalOfMember
from Member where joiningDay>='1 jan 2020' and joiningDay<'1 jan 2021'
group by Format(joiningday,'yyyy MM')
order by [Month]
Or if you want to have month wise cumulative count for members :
select Format(joiningday,'yyyy MM') [Month],sum(case when Format(joiningday,'yyyy MM') = Format(exitday,'yyyy MM') then 0 else 1 end)over(order by Format(joiningday,'yyyy MM')) TotalOfMember
from Member where joiningDay>='1 jan 2020' and joiningDay<'1 jan 2021'
group by Format(joiningday,'yyyy MM')
order by [Month]
Join the table to itself to eliminate same-month exiters:
select
year(a.joinjngday) Year,
month(a.joiningday) Month,
count(*) total
from Member a
join Member b on a.ID = b.ID
and month(b.exitday) = month(a.joinjngday)
and year(b.exitday) = year(a.joiningday)
where b.ID is null -- exclude same month exits
group by month(a.joiningday)
order by year(a.joinjngday), month(a.joiningday)
The most efficient way to do this is to use a cumulative sum. Basically, you want a + count and - count for each month based on the number of members who join and leave. I would approach this as:
with changes as (
select dateformparts(year(dte), month(dte), 1) as yyyymm,
sum(inc) as month_changes
from members m cross apply
(values (joiningday, 1),
(exitday, -1)
) v(dte, inc)
)
select yyyymm, sum(month_changes)
from changes
group by yyyymm
order by yyyymm;
If you want this for a particular period of time, then filter the above. Also, this will not contain months that have no changes.
If you wanted this for just a handful of months -- even those with no changes -- then you might find that explicit counting is simpler:
select d.dte,
(select count(*)
from members m
where m.joiningday <= eomonth(d.dte) and
m.exitday > eomonth(d.dte)
) as members_in_month
from (values (convert(date, '2021-01-01')),
(convert(date, '2021-02-01')),
(convert(date, '2021-03-01'))
) d(dte);

sql user retention calculation

I have a table records like this in Athena, one user one row in a month:
month, id
2020-05 1
2020-05 2
2020-05 5
2020-06 1
2020-06 5
2020-06 6
Need to calculate the percentage=( users come both prior month and current month )/(prior month total users).
Like in the above example, users come both in May and June 1,5 , May total user 3, this should calculate a percentage of 2/3*100
with monthly_mau AS
(SELECT month as mauMonth,
date_format(date_add('month',1,cast(concat(month,'-01') AS date)), '%Y-%m') AS nextMonth,
count(distinct userid) AS monthly_mau
FROM records
GROUP BY month
ORDER BY month),
retention_mau AS
(SELECT
month,
count(distinct useridLeft) AS retention_mau
FROM (
(SELECT
userid as useridLeft,month as monthLeft,
date_format(date_add('month',1,cast(concat(month,'-01') AS date)), '%Y-%m') AS nextMonth
FROM records ) AS prior
INNER JOIN
(SELECT
month ,
userid
FROM records ) AS current
ON
prior.useridLeft = current.userid
AND prior.nextMonth = current.month )
WHERE userid is not null
GROUP BY month
ORDER BY month )
SELECT *, cast(retention_mau AS double)/cast(monthly_mau AS double)*100 AS retention_mau_percentage
FROM monthly_mau as m
INNER JOIN monthly_retention_mau AS r
ON m.nextMonth = r.month
order by r.month
This gives me percentage as 100 which is not right. Any idea?
Hmmm . . . assuming you have one row per user per month, you can use window functions and conditional aggregation:
select month, count(*) as num_users,
sum(case when prev_month = dateadd('month', -1, month) then 1 else 0 end) as both_months
from (select r.*,
cast(concat(month, '-01') AS date) as month_date,
lag(cast(concat(month, '-01') AS date)) over (partition by id order by month) as prev_month_date
from records r
) r
group by month;

How can I display a result of data in order by a month-year combine column in sql?

I want to display a below data in order by first take month and then year
count Date
------- ----------
5 Aug 2011
6 jan 2008
10 feb 2009
I want to result as a first display a 2008 year, then 2009 like wise ordering wise date and also should display month in order wise
Assumptions:
You are trying to count records grouping by year and month
You have a table named Table1 with a column named EventDate
You are using SQL Server (you didn't specify)
You don't mind having extra columns in the output (you can ignore the columns you don't need)
You want to order by count, then year, then month
Based on these assumptions, the following should give you what you want.
SELECT COUNT(*) AS Count,
CONVERT(CHAR(3), DATENAME(MONTH, EventDate))
+ ' ' + CONVERT(CHAR(4), YEAR(EventDate)) AS Date,
MIN(YEAR(EventDate)) AS Year, MIN(MONTH(EventDate)) AS Month
FROM Table1
GROUP BY CONVERT(CHAR(4), YEAR(EventDate)),
CONVERT(CHAR(3), DATENAME(MONTH, EventDate))
ORDER BY COUNT(*), Year, Month
Here is the solution..
select convert(char(3), Date, 0)+' '+RIGHT(CONVERT(varchar, YEAR(Date)), 4) as [Date]
,count(id) as Count from Tabletest
group by convert(char(3), Date, 0)+' '+ RIGHT(CONVERT(varchar, YEAR(Date)), 4),month(Date),YEAR(Date)
order by YEAR(Date),MONTH(Date)

Select only months which have data for a specified Year

I would like a query which selects only those month's which have data for a specified year but I'm not quite sure how to achieve this. Here is what I have got so far:
select MONTH(DateRaised) as 'Month'
from Complaints
where
(select COUNT(*)
from Complaints
where YEAR(DateRaised) = 2000) > 0
group by MONTH(dateraised)
order by MONTH(dateraised)
So if my data had a Complaint from May, August and December in 2000, then I would only like 5, 8 and 12 to appear in my query, is this possible?
select DISTINCT MONTH(DateRaised) AS 'Month'
from Complaints
where YEAR(DateRaised) = 2000
select MONTH(DateRaised) as 'Month'
from Complaints
where YEAR(DateRaised) = 2000
ORDER BY MONTH(dateraised)
SELECT MONTH(DateRaised) as 'Month', COUNT(*) AS count
FROM Complaints
WHERE YEAR(DateRaised) = 2000
GROUP BY MONTH(dateraised)
ORDER BY MONTH(dateraised)