select multiple sum how to filter by date correctly - sql

Here is what I have currently that does not filter anything by createdDate.
SELECT [employeeID]
,employeeName
,isnull((SELECT SUM(case when clientID != 10 then timeSpent else 0 end)),0) as 'billable'
,isnull((SELECT SUM(case when clientID = 10 then timeSpent else 0 end)),0) as 'nonBillable'
FROM [myDB].[dbo].[myTable]
group by employeeID,employeeName
which outputs:
employeeID employeeName billable nonbillable
---------- ------------ -------- -----------
1 tom 5230 2302
2 dick 25 8439
3 harry 2430 9433
accurate output would be similar but with sum of values only within the date range:
employeeID employeeName billable nonbillable
---------- ------------ -------- -----------
1 tom 35 5
2 dick 25 15
3 harry 2 48
[myTable] has the following fields: employeeID,employeeName,clientID,timeSpent,createdDate
I need to be able to add a filter in to each of the select sum statements similar to the following: WHERE createdDate BETWEEN ('2012-10-01') AND ('2012-10-07')
The following variations all fail either with SQL Errors or inaccurate output:
SELECT [employeeID]
,employeeName
,isnull((SELECT SUM(case when clientID != 10 then timeSpent else 0 end)),0) as 'billable'
,isnull((SELECT SUM(case when clientID = 10 then timeSpent else 0 end)),0) as 'nonBillable'
FROM [myDB].[dbo].[myTable]
WHERE createdDate BETWEEN ('2012-10-01') AND ('2012-10-07')
group by employeeID,employeeName
SELECT DISTINCT [employeeID]
,employeeName
,isnull((SELECT SUM(case when clientID != 10 then timeSpent else 0 end)),0) as 'billable'
,isnull((SELECT SUM(case when clientID = 10 then timeSpent else 0 end)),0) as 'nonBillable'
FROM [myDB].[dbo].[myTable]
WHERE createdDate BETWEEN ('2012-10-01') AND ('2012-10-07')
group by employeeID,employeeName
SELECT [employeeID]
,employeeName
,isnull((SELECT SUM(case when clientID != 10 then timeSpent else 0 end)WHERE createdDate BETWEEN ('2012-10-01') AND ('2012-10-07')),0) as 'billable'
,isnull((SELECT SUM(case when clientID = 10 then timeSpent else 0 end)WHERE createdDate BETWEEN ('2012-10-01') AND ('2012-10-07')),0) as 'nonBillable'
FROM [myDB].[dbo].[myTable]
group by employeeID,employeeName,createdDate
Any help would be greatly appreciated.
Thanks in advance.

The first query should give you the correct results
SELECT [employeeID]
,employeeName
,isnull((SELECT SUM(case when clientID != 10 then timeSpent else 0 end)),0) as 'billable'
,isnull((SELECT SUM(case when clientID = 10 then timeSpent else 0 end)),0) as 'nonBillable'
FROM [myDB].[dbo].[myTable]
WHERE createdDate BETWEEN '2012-10-01' AND '2012-10-07'
group by employeeID,employeeName
However, if createdDate is a datetime type, then it will only return values between '2012-01-01 00:00' and '2012-10-07 00:00' - nothing after 2012-10-07 00:01. Ideally you would specify the filter dates as dates, rather than strings.

Related

Tolerance with Min Max

I am trying to adjust the below code by adding a 2 week tolerance piece.
What it does it looks when the first time a customer (identifier) created a request and the first time it was completed and counts the days which happened in between.
However I am trying to add a tolerance piece. Which says count the number of NCO which occurred between those dates and if there were further requests past the completion date which happened within 2 weeks of the completion date then count those as well (part of the same request). Anything past 2 weeks of the completions date consider as a new request.
CREATE TABLE #temp
(
Identifier varchar(40)NOT NULL
,Created_Date DATETIME NOT NULL
,Completed_Date DATETIME NULL
,SN_Type varchar(20) NOT NULL
,SN_Status varchar(20) NOT NULL
)
;
INSERT INTO #temp
VALUES ('3333333','2017-02-14 15:00:40.000','2017-02-15 00:00:00.000','Re-Activattion', 'COMP');
INSERT INTO #temp
VALUES ('3333333','2017-05-24 16:41:04.000','2017-06-05 00:00:00.000','Re-Activattion', 'N-CO');
INSERT INTO #temp
VALUES ('3333333','2017-05-25 11:49:54.000','2017-05-26 00:00:00.000','Re-Activattion', 'COMP');
INSERT INTO #temp
VALUES ('3333333','2017-06-27 10:24:29.000',NULL,'Re-Activattion', 'ACC');
#Alex you code is accurate just I would like to be selecting the min date the record is created a 2nd time, so line 2 of the result should return min date to be 2017-05-24 16:41:04.000.
select identifier
,case
when sum(case when SN_STATUS='COMP' and SN_TYPE = 'Re-Activattion' then 1 else 0 end)>0
then str(datediff(day
,MIN(case
when SN_TYPE = 'Re-Activattion'
then Created_Date
else null
end
)
,min(case
when (SN_TYPE = 'Re-Activattion'
and SN_STATUS='COMP'
)
then Completed_Date
else null
end
)
)
)
when sum(case when SN_TYPE='Re-Activattion' then 1 else 0 end)>0
then 'NOT COMP'
else 'NO RE-ACT'
end
as RE_ACT_COMPLETION_TIME
,Sum(CASE WHEN SN_STATUS = 'N-CO' THEN 1 ELSE 0 END) as [RE-AN NCO #]
from #temp
group by identifier
;
RESULTS I AM AFTER:
Your table design is not optimal for these kinds of queries as there is no definitive record that specified order start and order end. Additionally multiple orders are stored with the same identifier.
To work around this you need to calculate/identify Order start and Order End records yourself.
One way to do it is using Common Table Expressions.
Note: I have added comments to code to explain what each section does.
-- calculate/identify Order start and Order End records
WITH cte AS
(
-- 1st Order start record i.e. earliest record in the table for a given "Identifier"
SELECT Identifier, MIN( Created_Date ) AS Created_Date, CONVERT( VARCHAR( 30 ), 'Created' ) AS RecordType, 1 AS OrderNumber
FROM #temp
GROUP BY Identifier
UNION ALL
-- All records with "COMP" status are treated as order completed events. Add 2 weeks to the completed date to create a "dummy" Order End Date
SELECT Identifier, DATEADD( WEEK, 2, Created_Date ) AS Created_Date, 'Completed' AS RecordType, ROW_NUMBER() OVER( PARTITION BY Identifier ORDER BY Created_Date ) AS OrderNumber
FROM #temp
WHERE SN_STATUS = 'COMP'
UNION ALL
-- Set the start period of the next order to be right after (3 ms) the previous Order End Date
SELECT Identifier, DATEADD( ms, 3, DATEADD( WEEK, 2, Created_Date )) AS Created_Date, 'Created' AS RecordType, ROW_NUMBER() OVER( PARTITION BY Identifier ORDER BY Created_Date ) + 1 AS OrderNumber
FROM #temp
WHERE SN_STATUS = 'COMP'
),
-- Combine Start / End records into one record
OrderGroups AS(
SELECT Identifier, OrderNumber, MIN( Created_Date ) AS OrderRangeStartDate, MAX( Created_Date ) AS OrderRangeEndDate
FROM cte
GROUP BY Identifier, OrderNumber
)
SELECT a.Identifier, a.OrderNumber, OrderRangeStartDate, OrderRangeEndDate,
case
when sum(case when SN_STATUS='COMP' and SN_TYPE = 'Re-Activattion' then 1 else 0 end)>0
then str(datediff(day
,MIN(case
when SN_TYPE = 'Re-Activattion'
then Created_Date
else null
end
)
,min(case
when (SN_TYPE = 'Re-Activattion'
and SN_STATUS='COMP'
)
then Completed_Date
else null
end
)
)
)
when sum(case when SN_TYPE='Re-Activattion' then 1 else 0 end)>0
then 'NOT COMP'
else 'NO RE-ACT'
end as RE_ACT_COMPLETION_TIME,
Sum(CASE WHEN SN_STATUS = 'N-CO' THEN 1 ELSE 0 END) as [RE-AN NCO #]
FROM OrderGroups AS a
INNER JOIN #Temp AS b ON a.Identifier = b.Identifier AND a.OrderRangeStartDate <= b.Created_Date AND b.Created_Date <= a.OrderRangeEndDate
GROUP BY a.Identifier, a.OrderNumber, OrderRangeStartDate, OrderRangeEndDate
Output:
Identifier OrderNumber OrderRangeStartDate OrderRangeEndDate RE_ACT_COMPLETION_TIME RE-AN NCO #
-------------- ------------- ----------------------- ----------------------- ---------------------- -----------
200895691 1 2016-01-27 14:25:00.000 2016-02-10 15:15:00.000 0 2
200895691 2 2016-02-10 15:15:00.003 2017-01-16 12:15:00.000 1 1
Output for the updated data set:
Identifier OrderNumber OrderRangeStartDate OrderRangeEndDate RE_ACT_COMPLETION_TIME RE-AN NCO #
------------ ------------ ----------------------- ----------------------- ---------------------- -----------
200895691 1 2017-01-11 00:00:00.000 2017-03-27 00:00:00.000 61 4
200895691 2 2017-03-27 00:00:00.003 2017-04-20 00:00:00.000 1 1
3333333 1 2017-01-27 00:00:00.000 2017-02-10 00:00:00.000 0 2
44454544 1 2017-01-27 00:00:00.000 2017-01-27 00:00:00.000 NOT COMP 1
7777691 1 2017-02-08 09:36:44.000 2017-02-22 09:36:44.000 63 1
Update 2017-10-05 in response to the comment
Input:
INSERT INTO #temp VALUES
('11111','20170203','20170203','Re-Activattion', 'COMP'),
('11111','20170206','20170202','Re-Activattion', 'N-CO');
Output:
Identifier OrderNumber OrderRangeStartDate OrderRangeEndDate RE_ACT_COMPLETION_TIME RE-AN NCO #
---------- ------------ ----------------------- ----------------------- ---------------------- -----------
11111 1 2017-02-03 00:00:00.000 2017-02-17 00:00:00.000 0 1

Count grouped colums and group them via other column

I have a little problem.
The data:
2016-11-09 0536B088-D3DE-4C0E-903F-C2463D0AAB7E
2016-11-09 866D70EC-93FD-4C30-BC54-C7B954F255BE
2016-11-09 6C090D6B-9842-4CB0-9E10-F9B941C8D3A1
2016-11-09 FB1DD63E-F098-4191-B8F4-BEA4F9776B54
2016-11-09 FB1DD63E-F098-4191-B8F4-BEA4F9776B54
2016-11-10 0536B088-D3DE-4C0E-903F-C2463D0AAB7E
2016-11-10 NULL
2016-11-10 0536B088-D3DE-4C0E-903F-C2463D0AAB7E
2016-11-11 0536B088-D3DE-4C0E-903F-C2463D0AAB7E
2016-11-11 0536B088-D3DE-4C0E-903F-C2463D0AAB7E
From it I want to count UserId and group via Date.
I should be like this:
Date | Unique | Returning | New
..09 | 4 | 1 | 3
..10 | 2 | 1 | 1
..11 | 1 | 1 | 0
How I can do it?
I have this query.
select
cast(EventTime as date) as 'Date',
count(distinct UserId) + count(distinct case when UserId is null then 1 end) as 'Unique users',
0 as 'Returning users',
0 as 'New users'
from
TelemetryData
where
DiscountId = '5F8851DD-DF77-46DC-885E-46ECA93F021C' and EventName = 'DiscountClick'
group by
cast(EventTime as date)`
Unique users = unique with NULL too!
Returing users = UserId who clicked more than 1 times isnull(sum(case when UserId(here shoudld be count) > 1 then 1 else 0 end), 1)
New users who clicked only one! isnull(sum(case when UserId(count also) = 1 then 1 else 0 end), 1)
#EDIT:
Ok, two of your results work perfect. But I need now integrate it with other query.
SELECT
'5F8851DD-DF77-46DC-885E-46ECA93F021C',
cast([dbo].[TelemetryData].[EventTime] as date) as 'Date',
sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountLike' then 1 else 0 end) as 'Likes',
sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountDislike' then 1 else 0 end) as 'Dis likes',
sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountSharing' then 1 else 0 end) as 'Shares',
SUM(case when [dbo].[TelemetryData].[EventName]='DiscountView' then 1 else 0 end) as 'Views',
SUM(case when [dbo].[TelemetryData].[EventName]='DiscountClick' then 1 else 0 end) as 'Clicks',
Sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountCode' then 1 else 0 end) as 'Downloaded codes',
Sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountSave' then 1 else 0 end) as 'Saves',
sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountClickWWW' then 1 else 0 end) as 'Page redirections',
Round(
cast(Sum(case when [dbo].[TelemetryData].[EventName]='DiscountClick' then 1 else 0 end) as float)
/
cast(
case when SUM(case when [dbo].[TelemetryData].[EventName]='DiscountView' then 1 else 0 end) = 0 then 1
else SUM(case when [dbo].[TelemetryData].[EventName]='DiscountView' then 1 else 0 end) end as float)
* 100, 2)
as 'Average CTR',
0 as 'Unique users',
0 as 'New users',
0 as 'Returning users',
Sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountCommentPositive' then 1 else 0 end) as 'Positive comments',
sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountCommentNegative' then 1 else 0 end) as 'Negative comments'
from [dbo].[TelemetryData]
where [dbo].[TelemetryData].[DiscountId] = '5F8851DD-DF77-46DC-885E-46ECA93F021C'
and ([dbo].[TelemetryData].[EventName] = 'DiscountView' or [dbo].[TelemetryData].[EventName] = 'DiscountClick' or
[dbo].[TelemetryData].[EventName] = 'DiscountDislike' or [dbo].[TelemetryData].[EventName] = 'DiscountCode' or
[dbo].[TelemetryData].[EventName] = 'DiscountLike' or [dbo].[TelemetryData].[EventName] = 'DiscountSharing' or
[dbo].[TelemetryData].[EventName] = 'DiscountClickWWW' or [dbo].[TelemetryData].[EventName] = 'DiscountSave' or
[dbo].[TelemetryData].[EventName] = 'DiscountCommentPositive' or [dbo].[TelemetryData].[EventName] = 'DiscountCommentNegative')
group by cast([dbo].[TelemetryData].[EventTime] as date)
order by cast([dbo].[TelemetryData].[EventTime] as date) asc
Now it will be hard...
You want aggregated user information in your results. One obvious and simple solution is to group by date and user first so as to get this information per user and date and only later group by date only.
select
eventdate,
count(*) as unique_users,
count(case when cnt > 1 then 1 end) as returning_users,
count(case when cnt = 1 then 1 end) as new_users
from
(
select cast(eventtime as date) as eventdate, userid, count(*) as cnt
from telemetrydata
where ...
group by cast(eventtime as date), userid
) date_user
group by eventdate;
Could be i don't understand you question but looking to your data seems that you need
select
date
, count(*) as unique
, (count(*) - count(distinct user_id)) as returning
, count(distinct user_id) as new
group by date
were user_id is not null
Try this using a Common Table Expression:
Setup
CREATE TABLE #TelemetryData
(
EventTime Date,
UserId UNIQUEIDENTIFIER NULL
)
INSERT INTO #TelemetryData
VALUES
('2016-11-09', '0536B088-D3DE-4C0E-903F-C2463D0AAB7E'),
('2016-11-09', '866D70EC-93FD-4C30-BC54-C7B954F255BE'),
('2016-11-09', '6C090D6B-9842-4CB0-9E10-F9B941C8D3A1'),
('2016-11-09', 'FB1DD63E-F098-4191-B8F4-BEA4F9776B54'),
('2016-11-09', 'FB1DD63E-F098-4191-B8F4-BEA4F9776B54'),
('2016-11-10', '0536B088-D3DE-4C0E-903F-C2463D0AAB7E'),
('2016-11-10', NULL),
('2016-11-10', '0536B088-D3DE-4C0E-903F-C2463D0AAB7E'),
('2016-11-11', '0536B088-D3DE-4C0E-903F-C2463D0AAB7E'),
('2016-11-11', '0536B088-D3DE-4C0E-903F-C2463D0AAB7E')
Query
;WITH CTE
AS
(
SELECT EventTime,
UserId,
COUNT(*) cnt,
ROW_NUMBER() OVER (PARTITION BY EventTime ORDER BY EventTime) RN
FROM #TelemetryData
GROUP BY EventTime, UserId
)
SELECT EventTime,
MAX(RN) AS [Unique],
SUM(CASE WHEN cnt > 1 THEN 1 ELSE 0 END) as New,
SUM(CASE WHEN cnt = 1 THEN 1 ELSE 0 END) AS Returning
FROM CTE
GROUP BY EventTime
Results
EventTime Unique New Returning
2016-11-09 4 1 3
2016-11-10 2 1 1
2016-11-11 1 1 0
Try below query
select Date, uniques, returning, uniques-returning as new
from (
select Date,
sum(case when row_num = 1 then 1 else 0 end) uniques,
sum(case when row_num = 2 then 1 else 0 end) returning
from(
select cast(EventTime as date) as Date,
ROW_NUMBER() over(partition by EventTime, userid order by EventTime) row_num
from TelemetryData) cte1
group by Date)cte2
Hope this should help you
The following query should work:
select EventTime,
max(DistinctRank) [Unique],
sum(CountOfDistinct - 1) Returning,
max(DistinctRank) - sum(CountOfDistinct - 1) New
from
(select distinct EventTime,
UserId,
rank() over (partition by EventTime order by UserId) DistinctRank,
count(1) over (partition by EventTime, UserId) CountOfDistinct
from TelemetryData) sub
group by EventTime
The subquery (run it separately and see for yourself) will return the unique combinations of EventTime and UserID, along with the the rank of each unique UserId for a given date, and the count of distinct values for each combination of EventTime and UserId:
EventDate UserId DistinctRank CountOfDistinct
2016-11-09 00:00:00.000 0536B088-D3DE-4C0E-903F-C2463D0AAB7E 1 1
2016-11-09 00:00:00.000 6C090D6B-9842-4CB0-9E10-F9B941C8D3A1 2 1
2016-11-09 00:00:00.000 866D70EC-93FD-4C30-BC54-C7B954F255BE 3 1
2016-11-09 00:00:00.000 FB1DD63E-F098-4191-B8F4-BEA4F9776B54 4 2
2016-11-10 00:00:00.000 NULL 1 1
2016-11-10 00:00:00.000 0536B088-D3DE-4C0E-903F-C2463D0AAB7E 2 2
2016-11-11 00:00:00.000 0536B088-D3DE-4C0E-903F-C2463D0AAB7E 1 2
Then the outer query gets the maximum DistinctRank for each unique pair, which is the number of unique UserIds for the EventDate, and essentially the sum of the subquery records where there were duplicates in UserId for a given EventDate, which is the number of returning users. The New column is just the difference between Unique and Returning. The result is:
Event Date Unique Returning New
2016-11-09 00:00:00.000 4 1 3
2016-11-10 00:00:00.000 2 1 1
2016-11-11 00:00:00.000 1 1 0

Data according to time

I have table1 in this data is
ID Name StartDate EndDate
1 Paris 2014-02-01 00:00:00.000 2014-02-28 23:59:59.000
2 UK 2014-02-01 00:00:00.000 2014-02-28 23:59:59.000
3 France 2014-02-01 00:00:00.000 2014-02-28 23:59:59.000
and sp is
ALTER procedure [dbo].[spdata]
#fromdate datetime,
#todate datetime,
#Region varchar(50)
as
Select (Select Sum(Convert(int,SF)) from RVU inner dbo.VI vh on RVU.FID = vh.FID WHERE vh.No = Q.No and ID in (
Select ID from RU WHERE CAST(StartDate as date)>= CAST(#fromdate as date) and CAST(EndDate as date)<= CAST(#todate as date)
)) as SF
from (
Select
S.Name,
S.No,
SUM(Case when s.Vme='Car' then total else 0 end) as CAR,
SUM(Case when s.Vme='Tin' then total else 0 end) as Tin,
SUM(Case when s.Vme='Cake' then total else 0 end) as Cake,
SUM(Case when s.Vme='Flow' then total else 0 end) as Flow,
SUM(Case when s.Vme='Unit' then total else 0 end) as Unit,
SUM(total) total ,
MAX(S.Speed) Speed
from (
Select vh.Name as Name,vh.No as No,VV.Vame,count(VV.Vme) as total, RV.SF as MA,
RV.Speed from VVU VV inner join RVU RV on VV.MID=RV.ID inner join RU RU on RV.ID=RU.ID
left join dbo.VI vh on RV.FID = vh.FID WHERE CAST(RU.StartDate as date)>= CAST(#fromdate as date) and CAST(RU.EndDate as date)<= CAST(#todate as date) and
RU.Name_C= #Name_C AND Vme <> '' Group By vh.Name, vh.No, VV.Vme, RV.SF,
RV.Speed ) S GROUP BY s.RegNo, s.Name) Q
from that sp when i enter parameters DATA IS
[spdata] '2016-07-01 00:00:00.000', '2016-07-31 23:59:59.000', 'pARIS'
Name No CAR Tin Cake Flow Unit total Speed SF
John 412 0 0 12 0 5 17 82 60
Mike 48 2 1 5 1 3 9 160 464
ACNme 438 0 1 5 2 3 11 10 264
XYZ 248 0 1 5 3 3 12 60 244
now i want when i change time '2016-07-01 00:00:00.000', '2016-07-31 23:59:59.000',
like this
'2016-07-01 02:02:00.000', '2016-07-31 12:59:59.000',
then records also reflect on this time means according to date plus time data will be display
Don't cast your StartDate , EndDate , #fromdate , #todate as Date.
`Alter procedure [dbo].[spdata]
#fromdate datetime,
#todate datetime,
#Region varchar(50)
as
Select (Select Sum(Convert(int,SF)) from RVU inner dbo.VI vh on RVU.FID = vh.FID WHERE vh.No = Q.No and ID in (
Select ID from RU WHERE StartDate >= #fromdate and EndDate <=#todate
)) as SF
from (
Select
S.Name,
S.No,
SUM(Case when s.Vme='Car' then total else 0 end) as CAR,
SUM(Case when s.Vme='Tin' then total else 0 end) as Tin,
SUM(Case when s.Vme='Cake' then total else 0 end) as Cake,
SUM(Case when s.Vme='Flow' then total else 0 end) as Flow,
SUM(Case when s.Vme='Unit' then total else 0 end) as Unit,
SUM(total) total ,
MAX(S.Speed) Speed
from (
Select vh.Name as Name,vh.No as No,VV.Vame,count(VV.Vme) as total, RV.SF as MA,
RV.Speed from VVU VV inner join RVU RV on VV.MID=RV.ID inner join RU RU on RV.ID=RU.ID
left join dbo.VI vh on RV.FID = vh.FID WHERE RU.StartDate >= #fromdate and RU.EndDate <= #todate and
RU.Name_C= #Name_C AND Vme <> '' Group By vh.Name, vh.No, VV.Vme, RV.SF,
RV.Speed
) S GROUP BY s.RegNo, s.Name) Q`

tsql query efficiency

I have a table that is defined as follows:
CREATE TABLE [dbo].[ListingStats](
[ListingStatID] [int] IDENTITY(1,1) NOT NULL,
[StatTypeID] [int] NOT NULL,
[CreatedDate] [date] NOT NULL,
[ListingID] [int] NOT NULL,
CONSTRAINT [PK_ListingStats] PRIMARY KEY CLUSTERED
(
[ListingStatID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
I am trying to get 4 totals for each type (listingStatTypeID) for today, last 7 days, last 30 days, and all time.
I am not really sure what the most efficient query will be. Right now I have the following that I can repeat for each TYPE but that will be a big query and it will be a lot of calls.
declare #listingID int
set #listingID = 209722
--today
select count(1) from ListingStats where listingid = #listingid and CreatedDate = getdate()
--last 7 days
select count(1) from ListingStats where listingid = #listingid and CreatedDate > getdate()-7
--last 30 days
select count(1) from ListingStats where listingid = #listingid and CreatedDate > getdate()-30
--all time
select count(1) from ListingStats where listingid = #listingid
I am always calling this for one listing at a time by providing a listingID.
If anyone could provide a direction I would appreciate it. Should I create a view of some sort?
Expected Results
-Type------Today-----7Days---30Days---Ever
1 44 50 500 5000
2 22 40 90 1000
3 55 55 555 5555
For a single listing, you can use CASE expressions to get the four values in a single query:
SELECT SUM(CASE WHEN CreatedDate = getdate() THEN 1 ELSE 0 END) AS v_today,
SUM(CASE WHEN CreatedDate > getdate()-7 THEN 1 ELSE 0 END) AS v_week,
SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
COUNT(*) AS v_alltime
FROM ListingStats
WHERE listingid = #listingid
For all listing IDs, then
SELECT ListingID,
SUM(CASE WHEN CreatedDate = getdate() THEN 1 ELSE 0 END) AS v_today,
SUM(CASE WHEN CreatedDate > getdate()-7 THEN 1 ELSE 0 END) AS v_week,
SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
COUNT(*) AS v_alltime
FROM ListingStats
GROUP BY ListingID
If you want to get summaries for each StatTypeID (within a ListingID), then:
SELECT ListingID,
StatTypeID,
SUM(CASE WHEN CreatedDate = getdate() THEN 1 ELSE 0 END) AS v_today,
SUM(CASE WHEN CreatedDate > getdate()-7 THEN 1 ELSE 0 END) AS v_week,
SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
COUNT(*) AS v_alltime
FROM ListingStats
GROUP BY ListingID, StatTypeID
If you want the summaries by StatTypeID across all ListingIDs, then:
SELECT StatTypeID,
SUM(CASE WHEN CreatedDate = getdate() THEN 1 ELSE 0 END) AS v_today,
SUM(CASE WHEN CreatedDate > getdate()-7 THEN 1 ELSE 0 END) AS v_week,
SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
COUNT(*) AS v_alltime
FROM ListingStats
GROUP BY StatTypeID
Judging from the 'expected results' section that has been added, this last query is closest to what you need. And judging from the comments, if you want the summaries by StatTypeID for a specific ListingID, then:
SELECT StatTypeID,
SUM(CASE WHEN CreatedDate = getdate() THEN 1 ELSE 0 END) AS v_today,
SUM(CASE WHEN CreatedDate > getdate()-7 THEN 1 ELSE 0 END) AS v_week,
SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
COUNT(*) AS v_alltime
FROM ListingStats
WHERE ListingID = #listingid
GROUP BY StatTypeID
If there are issues with your getdate() function calls (as suggested by Gordon Linoff in his answer), you also need to fix those.
You can do this with conditional aggregation. This puts the values into four columns:
select sum(case when CreatedDate = cast(getdate() as date) then 1 else 0 end) as today,
sum(case when CreatedDate > cast(getdate() - 7 as date) then 1 else 0 end) as lastweek,
sum(case when CreatedDate > cast(getdate() - 30 as date) then 1 else 0 end) as last30,
count(*) as ever
from ListingStats
where listingid = #listingid;
Note that getdate() returns a datetime, with a time component (despite the name), so this query casts the value to a date (removing the time component).
To get this for all listing ids:
select sum(case when CreatedDate = cast(getdate() as date) then 1 else 0 end) as today,
sum(case when CreatedDate > cast(getdate() - 7 as date) then 1 else 0 end) as lastweek,
sum(case when CreatedDate > cast(getdate() - 30 as date) then 1 else 0 end) as last30,
count(*) as ever
from ListingStats
group by listingid;

Fetch data in MS SQL 2008

I have three tables which are like:
table1
id,
created_Date
table2
id
district_ID
status_ID
table3
district_ID
district_Name
Now i need the records in following format
Srno District_name <10 days >10 and <20 days >20 days
1 xxx 12 15 20
2 yyy 8 0 2
count days as per current date
for example: if the created date is 10-08-2013 and current date is 13-08-2013 the date difference will be 3
So what should my query be? Any suggestions will be appreciated.
Thank you
table1
id created_Date
1 2013-07-12 13:32:10.957
2 2013-07-12 13:32:10.957
3 2013-08-01 10:00:10.957
4 2013-08-10 13:32:10.957
5 2013-08-10 14:32:10.957
table2
id district_ID status_id
1 1 3
2 2 3
3 2 7
4 3 4
5 4 3
table1
district_ID district_Name
1 xxx
2 yyy
3 zzz
4 aaa
5 bbb
I would have a look at using DATEDIFF and CASE.
DATEDIFF (Transact-SQL)
Returns the count (signed integer) of the specified datepart
boundaries crossed between the specified startdate and enddate.
Something like
SELECT District_name,
SUM(
CASE
WHEN DATEDIFF(day,created_Date, getdate()) < 10
THEN 1
ELSE 0
END
) [<10 days],
SUM(
CASE
WHEN DATEDIFF(day,created_Date, getdate()) >= 10 AND DATEDIFF(day,created_Date, getdate()) < 20
THEN 1
ELSE 0
END
) [>10 and <20 days],
SUM(
CASE
WHEN DATEDIFF(day,created_Date, getdate()) >= 20
THEN 1
ELSE 0
END
) [>20 days]
FROM Your_Tables_Here
GROUP BY District_name
;with cte as (
select t3.district_Name, datediff(day, t1.created_Date, getdate()) as diff
from table1 as t1 as t1
inner join table2 as t2 on t2.id = t1.id
inner join table3 as t3 on t3.district_id = t2.district_id
)
select
district_Name,
sum(case when diff < 10 then 1 else 0 end) as [<10 days],
sum(case when diff >= 10 and diff < 20 then 1 else 0 end) as [>=10 and < 20 days],
sum(case when diff >= 20 then 1 else 0 end) as [>= 20 days]
from cte
group by district_Name