Last 2 month record in SQL - sql-server

I try this SQL query to get current total and also last 2 months records and current month record means total 3 months..
Select distinct
tblRv.Owner,
(Select Count(*) as total from tblvv WHERE MasterID =tblRv.ID and Name <> '')
as currentdata
from tblRe
inner join tblRv
On tblRe.RID = tblRv.RID
WHERE
tblRe.StartDate between dateadd(m, -2, getdate()) and getdate() and
//tblRe.StartDate >= '2016-07-01 00:00:00' AND
//tblRe.EndDate <= '2016-07-08 23:59:59'
and tblRe.Region = 'uk' and
tblRv.Owner='Roh'
order by tblRv.Owner
when i exe this show me like this
OwnerName currentdata
Roh 1
Roh 2
Roh 3
Roh 5
and when i check individually write query and check from date 2016-07-01 and todate 2016-07-30 dates then this show me data 3 and 2016-06-01 00:00:00 and 2016-06-31 23:59:59 show me data 1 and 2016-05-01 00:00:00 ,2016-05-31 23:59:59 show me data 0
so i want data like this
owner july june may
roh 3 1 0
also when there will be current month i.e. aug then data must display last 2 months i.e.june july

Select
tblRv.Owner
,DATENAME(MONTH,tblRe.StartDate) as [Month]
,ISNULL(SUM(total),0) as currentdata
from tblRe
INNER JOIN tblRv ON tblRe.RID = tblRv.RID
LEFT JOIN (
Select Count(*) as total ,MasterID
from tblvv
WHERE Name <> ''
GROUP BY MasterID
) tblvv
ON tblvv.MasterID =tblRv.ID
WHERE tblRe.StartDate >= DATEADD(MONTH, -2, GETDATE())
AND tblRe.EndDate <= GETDATE()
AND tblRe.Region = 'uk'
AND tblRv.[Owner] ='Roh'
GROUP BY tblRv.Owner
,DATENAME(MONTH,tblRe.StartDate)
order by tblRv.[Owner]

You can try doing a pivot query where the three columns to be pivoted are the current, previous, and previous previous month in your data set. Note that I had to rewrite your query to remove the subqueries in the SELECT clause, because this makes it impossible to do aggregation of those columns.
SELECT tblRv.Owner,
SUM(CASE WHEN tblRe.StartDate = GETDATE() THEN t.total ELSE 0 END) AS currMonth,
SUM(CASE WHEN tblRe.StartDate = DATEADD(m, -1, GETDATE())
THEN t.total ELSE 0 END) AS prevMonth,
SUM(CASE WHEN tblRe.StartDate = DATEADD(m, -2, GETDATE())
THEN t.total ELSE 0 END) AS lastPrevMonth
FROM tblRe
INNER JOIN tblRv
ON tblRe.RID = tblRv.RID
INNER JOIN
(
SELECT MasterID, COUNT(*) AS total
FROM tblvv
GROUP BY MasterID
WHERE Name <> ''
) AS t
ON tblRv.ID = t.MasterID
WHERE tblRe.StartDate BETWEEN DATEADD(m, -2, GETDATE()) AND GETDATE() AND
tblRe.Region = 'uk' AND
tblRv.Owner = 'Roh'
GROUP BY tblRv.Owner
ORDER BY tblRv.Owner

Related

day wise and date range calculation

I am using Sql Server 2012.
This is how I calculate the ratio of failures in an order:
31 Days Table 1 query
sum(CASE
WHEN (datediff(dd,serDATE,'2015-01-21')) >= 31 THEN 31
WHEN (datediff(dd,serDATE,'2015-01-21')) < 0 THEN 0
ELSE (datediff(dd,serDATE,'2015-01-21'))END) as 31days
1 . How do i loop and pass dates dynamically in the Datediff?
31 Failures Table 2 query
SUM(Case when sometable.FAILUREDATE BETWEEN dateadd(DAY,-31,CONVERT(DATETIME, '2015-01-21 23:59:00.0', 102))
AND CONVERT(DATETIME, '2015-01-21 23:59:00.0', 102)Then 1 Else 0 END) As Failures31,
31 Day Cal(Formula)
((365*(Convert(decimal (8,1),T2.Failures31)/T1.31day))) [31dayCal]
This works fine when done for a specific order.
I want a similar kind of calculation done for day wise and month wise.
2. what approach should I be using to achieve day wise and month wise calculation?
I do also have a table called Calender with the list of dates that i can use.
I would really appreciate any help regarding this..Thank you..
Solution
DECLARE #StartDate date = 'Jan 1, 2015'
DECLARE #EndDate date = DATEADD(DAY, 30, #StartDate)
;WITH cte AS (
SELECT #StartDate AS ReportDate
UNION ALL
SELECT DATEADD(DAY, 1, ReportDate)
FROM cte
WHERE ReportDate < #EndDate
)
Select T1.[date],T1.Fail31,T2.days31,
((365*(Convert(decimal (8,1),T1.Fail31)/T2.days31))) [31Fly]
from
(
SELECT cte.ReportDate as [date],
SUM(Case when HISTORY.FAILUREDATE BETWEEN dateadd(DAY,-31,CONVERT(DATETIME, cte.ReportDate, 102))
AND CONVERT(DATETIME, cte.ReportDate, 102)Then 1 Else 0 END) As Fail31
FROM HISTORY left JOIN UNIT ON HISTORY.UNIT = UNIT.UNIT
CROSS JOIN cte
WHERE
UNIT.INSV_DATE < cte.ReportDate
AND UNIT.MODEL in('Toyota')
AND(UNIT.Customer in('Jona' ))
group by
cte.ReportDate ) T1
Inner Join
(SELECT cte.ReportDate as [date1],
COUNT(UNIT.UNIT) As Units,
sum(CASE
WHEN (datediff(dd,INSV_DATE,cte.ReportDate)) >= 31 THEN 31
WHEN (datediff(dd,INSV_DATE,cte.ReportDate)) < 0 THEN 0
ELSE (datediff(dd,INSV_DATE,cte.ReportDate))END) as days31
FROM UNIT
CROSS JOIN cte
WHERE
UNIT.INSV_DATE < cte.ReportDate
AND UNIT.MODEL in('Toyota')
AND(UNIT.Customer in('Jona' ))
group by
cte.ReportDate
) T2 on T1.[date] = t2.[date1]
Order by [date]

How to add Totals in SQL

I am trying to get the totals of each month as of YTD (Years to date) Can someone please help me figure out how to integrate this in my query? thank you This is what I have so far.
DECLARE #Year int
set #Year = 2013
select a.first_name, a.last_name
, COUNT(CASE WHEN MONTH(b.Funded_date) = 1 THEN 1 ELSE NULL END) January
, COUNT(CASE WHEN MONTH(b.Funded_date) = 2 THEN 1 ELSE NULL END) February
, COUNT(CASE WHEN MONTH(b.Funded_date) = 3 THEN 1 ELSE NULL END) March
, COUNT(CASE WHEN MONTH(b.Funded_date) = 4 THEN 1 ELSE NULL END) April
From tContact a Join tContract b ON a.contact_id = b.contract_id
Group by a.first_name, a.last_name
This is just an example of how you could count up rows that fall under a certain month.
SELECT MONTH(b.Funded_date) AS 'MonthNum',
COUNT(*) AS 'Total'
FROM Table AS b
WHERE YEAR(b.Funded_date) = 2014
GROUP BY MONTH(b.Funded_date)
Hopefully this will help you with your query.
Thanks
What I tried to do here is create an upper bound record for each month in tContract then join that back into the query you already had. It is joined on dates that are between the beginning of the year and the current month.
DECLARE #Year int
set #Year = 2013
select Ms.thismonth, count(B.thing_You_are_Totalling) from (
select thisMonth = dateadd(month,datediff(month,0,Funded_date),0)
from tContract
where moid = 2005405
and year(Funded_date) = #Year
group by dateadd(month,datediff(month,0,Funded_date),0)
) Ms
inner join (select * from tContact a inner join tContract ON a.contact_id = tContract.contract_id) B
on B.Funded_date >=dateadd(year,datediff(year,0,B.Funded_date),0) -- beginning of year
and B.Funded_date <= Ms.thisMonth -- this month
where year(B.Funded_date) = #Year -- restrict to only this year
group by thisMonth, first_name, last_name
I don't have your full table definition so there might be some issues (maybe a SqlFiddle is in order)
Not sure if this is what you are asking for.
select a.first_name, a.last_name
, COUNT(CASE WHEN MONTH(b.Funded_date) = 1 THEN 1 ELSE NULL END) January
, COUNT(CASE WHEN MONTH(b.Funded_date) = 2 THEN 1 ELSE NULL END) February
, COUNT(CASE WHEN MONTH(b.Funded_date) = 3 THEN 1 ELSE NULL END) March
, COUNT(CASE WHEN MONTH(b.Funded_date) = 4 THEN 1 ELSE NULL END) April
, COUNT(*) TotalCount
, SUM(CASE WHEN MONTH(b.Funded_date) = 1 THEN Amount ELSE NULL END) JanuaryAmount
, SUM(CASE WHEN MONTH(b.Funded_date) = 2 THEN Amount ELSE NULL END) FebruaryAmount
, SUM(CASE WHEN MONTH(b.Funded_date) = 3 THEN Amount ELSE NULL END) MarchAmount
, SUM(CASE WHEN MONTH(b.Funded_date) = 4 THEN Amount ELSE NULL END) AprilAmount
From tContact a Join tContract b ON a.contact_id = b.contact_id
WHERE YEAR(b.Funded_date) = #Year
Group by a.first_name, a.last_name
How about this:
declare #year int = 2013
select a.first_name
, a.last_name
, month(b.Funded_date) [Month]
, datename(month, dateadd(month, month(date_of_birth_dt), - 1)) [MonthName]
, count(month(b.Funded_date)) [Total]
from tContact a
where a.[Year] = #year
group by a.first_name, a.last_name, month(b.Funded_date)
It returns the total of each Month for the year 2013. a.[Year] might not the the name of the field that you have so adjust accordingly. Also, [Month] returns numeric value for month.
Use the Count(*) As Total function. I'm sure this will help you
SELECT MONTH(b.Funded_date) AS 'MonthNum',
COUNT(*) AS 'Total'
FROM Table AS b
WHERE YEAR(b.Funded_date) = 2014
GROUP BY MONTH(b.Funded_date)

tsql UNION without nulls

I have the following query
SELECT MONTH, COUNT(DISTINCT VISITS) AS BRAND_VISITS, NULL AS NONB_VISITS
FROM Table1
WHERE KEYWORD_TYPE = BRAND(
AND DATE >= '2013-01-01'
GROUP BY MONTH
UNION ALL
SELECT MONTH, NULL, COUNT(DISTINCT VISITS) AS NONB_VSTS
FROM Table1
WHERE KEYWORD_TYPE = NON-BRAND
AND DATE >= '2013-01-01'
GROUP BY MONTH
I get the following results:
1 352540 NULL
2 309834 NULL
3 228764 NULL
4 236054 NULL
5 218096 NULL
6 172527 NULL
1 NULL 5337
2 NULL 14120
3 NULL 9954
4 NULL 23755
5 NULL 19771
6 NULL 30797
However, what I want is inline results without NULLS
1 352540 5337
2 309834 14120
3 228764 9954
4 236054 23755
5 218096 19771
6 172527 30797
You can do this with using a single statement with CASE or with an JOIN on month instead of a UNION. If you take the join approach you may need to account for null values (no visist for a keyword in a month). You will want to profile them to see which is faster with your data and table structure. It is really all about the indexes and the amount of data you need to aggregate.
Assuming you don't have to worry about nulls based on the counts in your example, here is what you want.
SELECT brand.month, brand.brand_visits,nonbrand.non_brand_visits
FROM (SELECT month, COUNT(visits) AS brand_visits
FROM Table1
WHERE keyword_type = 'BRAND'
AND date >= '2013-01-01'
GROUP BY month) brand
INNER JOIN
(SELECT month, COUNT(visits) AS non_brand_visits
FROM Table1
WHERE keyword_type = 'NON-BRAND'
AND date >= '2013-01-01'
GROUP BY month) nonbrand
ON brand.month=nonbrand.month
Here is the CASE approach. You should profile based on your actual data you are aggregating and your indexes to see which method is faster.
SELECT month,
SUM(CASE WHEN keyword_type = 'BRAND' THEN 1 ELSE 0 END) AS brand_visits,
SUM(CASE WHEN keyword_type = 'NON-BRAND' THEN 1 ELSE 0 END) AS non_brand_visits
FROM Table1
WHERE date >= '2013-01-01'
GROUP BY month
Finally, you did not provide table structure or example data so I made some assumptions above. I strongly believe you did not need the COUNT(DISTINCT in your original statement. I have removed it and verified the two statement above yield the same results. If COUNT(DISTINCT is required then the CASE approach will not work but the join approach will still work fine.
Using your columns:
SELECT month,
count(distinct CASE WHEN keyword_type = 'BRAND' THEN visits END) AS BRAND_VISITS,
count(distinct CASE WHEN keyword_type = 'NON-BRAND' THEN visits END) AS NONB_VSTS
FROM Table1
WHERE date >= '2013-01-01'
and keyword_type in ('BRAND','NON-BRAND')
GROUP BY month
Am tempted to believe that month is simply the month from the date column, I would prefer this solution, it con cover more years than 1 and the same query will still be valid in the year 2014
SELECT cast(dateadd(month, datediff(month, 0, date), 0) as date) month,
count(distinct CASE WHEN keyword_type = 'BRAND' THEN visits END) AS BRAND_VISITS,
count(distinct CASE WHEN keyword_type = 'NON-BRAND' THEN visits END) AS NONB_VSTS
FROM Table1
WHERE date >= '2013-01-01'
and keyword_type in ('BRAND','NON-BRAND')
GROUP BY datediff(month, 0, date)
If you want to stick with your old script, you can fix it this way:
SELECT MONTH, max(BRAND_VISITS) BRAND_VISITS, max(NONB_VISITS) NONB_VISITS
FROM
(
SELECT MONTH, COUNT(DISTINCT VISITS) AS BRAND_VISITS, NULL AS NONB_VISITS
FROM Table1
WHERE KEYWORD_TYPE = 'BRAND'
AND DATE >= '2013-01-01'
GROUP BY MONTH
UNION ALL
SELECT MONTH, NULL, COUNT(DISTINCT VISITS) AS NONB_VSTS
FROM Table1
WHERE KEYWORD_TYPE = 'NON-BRAND'
AND DATE >= '2013-01-01'
GROUP BY MONTH
) a
GROUP BY MONTH

create a statistics table using datetime MSSQL Query

I have little table which gives me a very hard time:
Person datetime1 datetime2
Eric 2012-10-01 09:00:05.000 2012-10-01 22:00:00.000
Anna 2012-10-02 06:00:05.000 2012-10-03 12:00:05.000
Richard 2012-10-03 09:00:05.000 2012-10-04 02:00:05.000
Chuck 2012-10-01 12:00:05.000 2012-10-01 23:00:05.000
I am trying to write a query, which gives me statistics table. This table contains information about when a user logged in and out (daily granularity):
Date logged_in logged_off
2012-10-01 2 2
2012-10-02 1 0
2012-10-03 1 1
2012-10-04 0 1
According to my research, a pivot command could solve the problem?
select Person,
SUM(case when datetime1 = '2012-10-01' then 1 else 0 end) as [loggeed_in],
SUM(case when datetime2 = '2012-10-01' then 1 else 0 end) as [logged_of]
from table
group by Person
This is not working... Do you have any ideas?
This will fix the current query, but don't know if it will solve the whole problem...
select Person,
SUM(case when convert(varchar(10), datetime1, 111) = '2012/10/01' then 1 else 0 end) as [loggeed_in],
SUM(case when convert(varchar(10), datetime2, 111) = '2012/10/01' then 1 else 0 end) as [logged_of]
from table
group by Person
EDIT: I believe this will better suit requirements...
SELECT
[Date] = dt,
logged_in = (
SELECT COUNT(*)
FROM table1
WHERE convert(varchar(10), datetime1, 111) = convert(varchar(10), dt, 111)),
logged_off = (
SELECT COUNT(*)
FROM table1
WHERE convert(varchar(10), datetime2, 111) = convert(varchar(10), dt, 111))
FROM (
SELECT TOP 1000
row_number() OVER(ORDER BY (SELECT 0)) AS N
FROM master.dbo.syscolumns sc1, master.dbo.syscolumns sc2) tally
CROSS APPLY(
SELECT dt = DATEADD(dd, tally.N - 1, '2012-10-1')) tallydt
WHERE dt BETWEEN (SELECT MIN(dateadd(dd, -1, datetime1)) FROM table1) AND (SELECT MAX(datetime2) FROM table1)
GROUP BY dt
ORDER BY dt
Here is the working solution:
WITH O AS (
SELECT
CAST([login Date & Time] AS DATE) loginDate
,COUNT(*) logined
FROM table
GROUP BY CAST([login Date & Time] AS DATE)
), C AS (
SELECT
CAST([Close Date & Time] AS DATE) CloseDate
,COUNT(*) Closed
FROM table
WHERE [Close Date & Time] IS NOT NULL
GROUP BY CAST([Close Date & Time] AS DATE)
)
SELECT
COALESCE(C.CloseDate, O.loginDate) TheDate
--,O.loginDate
--,C.CloseDate
,O.logined
,C.Closed
FROM O
FULL JOIN C
ON O.loginDate = C.CloseDate
ORDER BY TheDate

SQL GROUP BY with COUNTS - how to always return a row when counts are 0

Following on from my previous question, I now have the following SQL:
SELECT CONVERT(VARCHAR(10), Date, 120) AS Date,
COUNT(*) AS Total,
COUNT(CASE
WHEN ErrorCode = -2 THEN 1
END) AS TimeOutErrors,
COUNT(CASE
WHEN ErrorCode IS NOT NULL THEN 1
END) AS TotalErrors
FROM Table
WHERE Type = 7
AND Date = CONVERT(VARCHAR(10), Dateadd(d, -1, Getdate()), 120)
GROUP BY Date
which returns all records of type 7 for yesterday with a count of -2 errors and a count of total errors.
However, this returns 0 rows if there are no records of type 7 for yesterday
Is it possible to get it to return all 0s when this is the case?
i.e.:
Date Total TimeOutErrors TotalErrors
---------- ----- ------------- -----------
2010-12-06 0 0 0
This query is being parsed by bcp to save to a log file daily using SQL Agent
You need an OUTER JOIN
...
FROM
(SELECT CONVERT(VARCHAR(10), Dateadd(d, -1, Getdate()), 120) AS [Date]) D
LEFT OUTER JOIN Table T
ON D.[Date] = T.[Date] AND T.Type = 7
GROUP BY D.[Date]

Resources