SQL Server : datetime incorrect results - sql

Using SQL Server 2008,
I have a procedure as follows:
SELECT
UserId, Name, Company, LanguageId, CodeRegisteredWith, TotalLoggedInDuration,
Region, IsAdmin,
IsRep, IsRetailer, IsTeamLeader, [dateregistered]
FROM
RoundupAcademy.dbo.UserProfile WITH(NOLOCK)
WHERE
(Convert(smalldatetime, DateRegistered, 120) >= Convert(smalldatetime, '2013-1-1', 120)
AND (Convert(smalldatetime, DateRegistered, 120) <= convert(smalldatetime, '2013-8-8', 120)))
This works fine and shows the results between the dates.
However when expanding on this query and some more conditions as follows:
SELECT
UserId, Name, Company, LanguageId, CodeRegisteredWith, TotalLoggedInDuration,
Region, IsAdmin, IsRep, IsRetailer, IsTeamLeader, [dateregistered]
FROM
RoundupAcademy.dbo.UserProfile WITH(NOLOCK)
WHERE
UserId is not null OR UserId not like ''
AND
(#LanguageID = 0 OR ([LanguageID] = #LanguageID ))
AND
((Convert(smalldatetime, DateRegistered, 120) >= Convert(smalldatetime, #datereg, 120)
AND (Convert(smalldatetime, DateRegistered, 120) <= convert(smalldatetime, #dateend, 120))))
it seems any date shows.
not sure what the problem is as my other conditions look fine.
any ideas?

Replace
WHERE UserId is not null OR UserId not like ''
with
WHERE (UserId is not null OR UserId not like '')
Otherwise you would get all records where UserId is not null or the other conditions are true.

query should be like these
SELECT UserId, Name, Company, LanguageId, CodeRegisteredWith, TotalLoggedInDuration, Region, IsAdmin,
IsRep, IsRetailer, IsTeamLeader, [dateregistered] FROM RoundupAcademy.dbo.UserProfile WITH(NOLOCK)
WHERE( UserId is not null OR UserId not like '')
AND
(#LanguageID = 0 OR ([LanguageID] = #LanguageID ))
AND
((Convert(smalldatetime,DateRegistered, 120) >= Convert(smalldatetime,#datereg, 120)
AND (Convert(smalldatetime,DateRegistered, 120) <= convert(smalldatetime,#dateend, 120))))

Related

Date filter on view output (dd/mm/yyy) SQL Server

I am taking output from a view that has a column CreatedDate which is returned in a dd/mm/yyyy format. I want to filter output on behalf of date but nothing is showing up. Can anybody help me?
SQL Server code:
;with CTE as
(
select
CreatedDate,
UserID,
UserName,
SUM([CreditedAmount]) as CreditedAmount,
SUM([TDSPercent]) as TDSPercent,
SUM([TDSAmount]) as TDSAmount,
SUM(ISNULL([ApplicationServicePercentage], 0)) as ApplicationServicePercentage,
SUM(ISNULL([ApplicationServiceAmount], 0)) as ApplicationServiceAmount,
SUM([CreditedAmount]) - SUM([DebitedAmount]) - SUM(ISNULL([TDSAmount], 0)) - SUM(ISNULL([ApplicationServiceAmount], 0)) as AmountToPay
from
[dbo].[vwGetPaymentStatement]
where
[Status] = 0
and UserStatus = 1
group by
UserID, UserName, CreatedDate
)
select
CreatedDate,
UserID, UserName,
CreditedAmount, TDSPercent, TDSAmount,
ApplicationServicePercentage,
ApplicationServiceAmount,
AmountToPay
from
CTE
where
AmountToPay is not null
and (UserID = #uid or UserName like '%' + #username + '%')
and (CreatedDate between #datefrom and #dateto)
Try casting to date if its not working?
(cast(CreatedDate as datetime) between #datefrom and dateto)
You hopefully already have your variables declared as datetime and dont need to cast those.
Based on your comments, and responses to other answers, I know that:
Your CreatedDate field is a VARCHAR
Your CreatedDate field has data which aren't proper dates.
I would start by running the definition of the CTE with one addition to help find the non-date values, which is as follows:
select
CreatedDate,
UserID,
UserName,
SUM([CreditedAmount]) as CreditedAmount,
SUM([TDSPercent]) as TDSPercent,
SUM([TDSAmount]) as TDSAmount,
SUM(ISNULL([ApplicationServicePercentage], 0)) as ApplicationServicePercentage,
SUM(ISNULL([ApplicationServiceAmount], 0)) as ApplicationServiceAmount,
SUM([CreditedAmount]) - SUM([DebitedAmount]) - SUM(ISNULL([TDSAmount], 0)) - SUM(ISNULL([ApplicationServiceAmount], 0)) as AmountToPay
from
[dbo].[vwGetPaymentStatement]
where
[Status] = 0
and UserStatus = 1
and isdate(createddate) = 0 --- > Added this row to find the non-date values
group by
UserID, UserName, CreatedDate
Once you figure out what to do with those non-date values you should be fine. Unless you have an issue with the data types of the #datefrom and #dateto variables.
SELECT createddate,
userid,
username,
creditedamount,
tdspercent,
tdsamount,
applicationservicepercentage,
applicationserviceamount,
amounttopay
FROM cte
WHERE amounttopay IS NOT NULL
AND ( userid = #uid
OR username LIKE '%' + #username + '%' )
AND ( createddate BETWEEN CONVERT(VARCHAR, Cast(#datefrom AS DATETIME),
103) AND
CONVERT(VARCHAR, Cast(#dateto AS DATETIME
), 103)

Loop Through 1 SQL Query, Instead Of Using 2 Queries

Below I have a variable with two basic SELECT statements. If the user can only use one variable, #StartDate, to enter a date parameter, how can a query be looped through to only use one SELECT statement instead of two like you see below. So, imagine you don't have both queries, but one query and it can only be ran once but satisfy the 2 conditions in the WHERE clauses below, which are "FullDate = #StartDate" and "Fulldate BETWEEN DATEADD(mm, DATEDIFF(mm, 0, #StartDate), 0) AND #StartDate". SO, essentially I am trying to squeeze two SELECT statements into one and provide the relevant data from both queries. UNION ALL cannot be used here.
DECLARE #StartDate DATE = '20170610'
SELECT
FirstName,
LastName,
SUM(MoneySpent) AS 'Spent'
FROM
TableOne
WHERE
FullDate = #StartDate;
GROUP BY FirstName, LastName
SELECT
FirstName,
LastName,
SUM(MoneySpent) AS 'Spent'
FROM
TableOne
WHERE
Fulldate BETWEEN DATEADD(mm, DATEDIFF(mm, 0, #StartDate), 0) AND #StartDate;
GROUP BY FirstName, LastName
If you have two dates #Date1 and #Date2, then you can use this:
SELECT
FirstName,
LastName,
SUM(CASE WHEN FullDate = #Date1 THEN MoneySpent ELSE 0 END) AS 'SpentDate1',
SUM(CASE WHEN FullDate = #Date2 THEN MoneySpent ELSE 0 END) AS 'SpentDate2'
FROM
TableOne
WHERE
FullDate = #Date1 OR FullDate = #Date2
GROUP BY FirstName, LastName
BTW, UNION ALL can be used as well, you just need wrap it as subquery and use additional GROUP BY
Something you need to know about BETWEEN is that it includes the endpoints, so you only need the second query to obtain what you are looking for.
SELECT
FirstName,
LastName,
SUM(MoneySpent) AS 'Spent'
FROM
TableOne
WHERE
Fulldate BETWEEN DATEADD(mm, DATEDIFF(mm, 0, #StartDate), 0) AND #StartDate;
GROUP BY FirstName, LastName
I think the first query is already covered by the second query.
SELECT FirstName ,
LastName ,
SUM(MoneySpent) AS 'Spent'
FROM TableOne
WHERE Fulldate BETWEEN DATEADD(mm, DATEDIFF(mm, 0, #StartDate), 0)
AND #StartDate
GROUP BY FirstName, LastName
But for the sake of argument, one of many options is that you can put the relevant data of each query into a temporary table.
E.g.
DECLARE #StartDate DATE = '2017.06.10';
IF ( OBJECT_ID('tempdb..#tempTbl') IS NOT NULL )
BEGIN
DROP TABLE #tempTbl
END
CREATE TABLE #tempTbl
(
ID INT IDENTITY(1, 1)
PRIMARY KEY ,
FirstName VARCHAR(100) ,
LastName VARCHAR(100) ,
Spent MONEY
)
INSERT INTO #tempTbl
( FirstName ,
LastName ,
Spent
)
SELECT FirstName ,
LastName ,
SUM(MoneySpent) AS 'Spent'
FROM TableOne
WHERE FullDate = #StartDate
INSERT INTO #tempTbl
( FirstName ,
LastName ,
Spent
)
SELECT FirstName ,
LastName ,
SUM(MoneySpent) AS 'Spent'
FROM TableOne
WHERE Fulldate BETWEEN DATEADD(mm, DATEDIFF(mm, 0, #StartDate), 0)
AND #StartDate
SELECT FirstName,LastName,Spent
FROM #tempTbl
GROUP BY FirstName, LastName
I think,Here you nitice that One Resultset is subset of another resultset.
In other word,Range Between condition satify equal condition.So result is not repeated.
Example using AdventureWorks2012
DECLARE #StartDate DATE = '20020224'
DECLARE #StartDate1 DATE = '20020303'
select a.BusinessEntityID
,a.RateChangeDate,sum(a.rate) Rate
from HumanResources.EmployeePayHistory a
where a.RateChangeDate
BETWEEN DATEADD(mm, DATEDIFF(mm, 0, #StartDate), 0) AND #StartDate
or a.RateChangeDate=#StartDate1
GROUP by a.BusinessEntityID,a.RateChangeDate
here Result of both date is visisble (6 rows)
if we make it this
DECLARE #StartDate DATE = '20020224'
DECLARE #StartDate1 DATE = StartDate
here since between condtion satify RateChangeDate=#StartDate1
so output is only 5 rows
so what you are thinking is cannot be achieve.
If I had same problem then I will use only select ... FullDate between
And in front end I will pull data for fulldate=#StartDate
If you really use 2 Select like now you doing then do this,
;With CTE as
(
SELECT
FirstName,
LastName,
Fulldate,
SUM(MoneySpent) AS 'Spent'
FROM
TableOne
WHERE
Fulldate BETWEEN DATEADD(mm, DATEDIFF(mm, 0, #StartDate), 0) AND #StartDate;
GROUP BY FirstName, LastName,Fulldate
)
select *,0 flg from cte
union ALL
select * ,1 flg from cte
where Fulldate=#StartDate

SQL Server : CASE-WHEN returns error in select list or Not-exist block if used in both

In the below SQL Server 2008 select statement Case-When is used in 2 places, in the select list and inside NOT EXISTS: CASE-1 and CASE-2.
It works only if I comment out one of case-when statements, only if I use it only in one place: select list OR not-exist.
If it used in both places, as below, I get error:
Conversion failed when converting date and/or time from character string.
I did my research, read http://www.fmsinc.com/free/newtips/sql/sqltip10.asp, but I still can not make it work.
Please help, what is wrong with code below? Thank you
MyTable.dob is nvarchar(10)
PayrollTable.date_of_birth is varchar(10)
Both dob columns are nullable.
MyTable.dob is in format mmddyy like '010255'.
PayrollTable.date_of_birth is in format 'mm/dd/yyyy' like '01/02/1955'
Code:
SELECT
FName,
LName,
( --- CASE-1
select
CASE
WHEN CONVERT(DATE, STUFF(STUFF(a.dob,3,0,'/'),6,0,'/')) > GETDATE()
THEN CONVERT(varchar(10), DATEADD(yy, -100, CAST(STUFF(STUFF(a.dob,3,0,'/'),6,0,'/') AS DATE)), 101)
ELSE CONVERT(varchar(10), CAST(STUFF(STUFF(a.dob,3,0,'/'),6,0,'/') AS DATE), 101)
END) as dob1
FROM
MyTable a
INNER JOIN
(SELECT
FName, LName, dob,
-- StartDate source format = yyyymm - 200104 , --- result = 2001-04-01 as DATE
MAX(CAST((STUFF(StartDate,5,0,'-') + '-01') AS DATE) ) as StartDate -- original format yyyymm
FROM
MyTable
WHERE
-- mmddyy
CAST(SUBSTRING( dob, 5, 2) as INT) > 31 --yy
AND dob != '999999'
GROUP BY
FName, LName, dob --'mmddyy'
) as t ON
LTRIM(RTRIM(a.FName)) = LTRIM(RTRIM(t.FName)) AND LTRIM(RTRIM(a.LName)) = LTRIM(RTRIM(t.LName))
AND
a.dob = t.dob --'mmddyy'
AND
CAST((STUFF(a.StartDate,5,0,'-') + '-01') AS DATE) = t.StartDate
WHERE ((LTRIM(RTRIM(a.FName)) != '' and
a.FName is not null) or
( LTRIM(RTRIM(a.LName)) != '' and a.LName is not null ) )
and
NOT EXISTS ----------------------------------
-- player does NOT exist in Party DIM alerady
(
select *
from PayrollTable p --- PARTY
where
p.date_of_birth = --t.dob -- varchar(10) 1980-09-07 p.date_of_birth
( -- CASE-2
select
CASE
WHEN CONVERT(DATE, STUFF(STUFF(t.dob,3,0,'/'),6,0,'/')) > CAST(GETDATE() as DATE) --t.dob
THEN CONVERT(varchar(10), DATEADD(yy, -100, CAST(STUFF(STUFF(t.dob,3,0,'/'),6,0,'/') AS DATE)), 101)
ELSE CONVERT(varchar(10), CAST(STUFF(STUFF(t.dob,3,0,'/'),6,0,'/') AS DATE), 101) --t.dob
END
)
and
p.first_name = t.FName
and
p.last_name = t.LName
)
your problem is here.
select *
from PayrollTable p --- PARTY
where
p.date_of_birth = --t.dob -- varchar(10) 1980-09-07 p.date_of_birth
( -- CASE-2
select
CASE
WHEN CONVERT(DATE, STUFF(STUFF(t.dob,3,0,'/'),6,0,'/')) > CAST(GETDATE() as DATE) --t.dob
THEN CONVERT(varchar(10), DATEADD(yy, -100, CAST(STUFF(STUFF(t.dob,3,0,'/'),6,0,'/') AS DATE)), 101)
-- MISSING A WHEN CONDITION HERE
THEN DATEADD(yy, -100, CAST(STUFF(STUFF('090780',3,0,'/'),6,0,'/') AS DATE))
ELSE CONVERT(varchar(10), CAST(STUFF(STUFF(t.dob,3,0,'/'),6,0,'/') AS DATE), 101) --t.dob
END
)

Complicated query involving res

I have the table as below and I need to have the query how many tasks created for the day and how many are resolved and I need to capture the Tasks which are passed from previous day with active status. Ex: TaskId 101 is created on 11/10/2014 and it is resolved on 11/12/2014 so it should show in the count of 11/11/2014 and 11/12/2014 also.
TaskId CreateDate Status ResolvedDate
101 11/10/2014 Resolved 11/12/2014
102 11/10/2014 Resolved 11/10/2014
103 11/11/2014 Active NULL
104 11/11/2014 Resolved 11/13/2014
105 11/13/2014 Active 11/13/2014
Please help me as I am not able to think of any solution. Sorry I was trying to post the table schema in table format but not able to create table and I am new to this forum.
#radar, You just gave me the hope with the query and I have changed the query as below and it started showing result. But the TotalActive showing less value than TotalCreated.
declare #start_date datetime = getdate()-30
declare #end_date datetime = getdate()
;WITH CTE AS
(
SELECT #start_date AS date
UNION ALL
SELECT DATEADD(day, 1, date) as date
FROM CTE
WHERE DATEADD(day, 1, date) <= #end_date
)
select cte.date,
sum( case when CONVERT(varchar, CreateDate, 101) <= CONVERT(varchar, cte.date, 101) and CONVERT(varchar, cte.date, 101) <= CONVERT(varchar, ResolveDate, 101) then 1 else 0 end
) as TotalActive,
sum( case when CONVERT(varchar, cte.date, 101) = CONVERT(varchar, CreateDate, 101) then 1 else 0 end
) as TotalCreated,
sum( case when CONVERT(varchar, cte.date, 101) = CONVERT(varchar, ResolveDate, 101) then 1 else 0 end
) as TotalResolved
from cte
left join [WarehouseIncidents] T
ON CONVERT(varchar, CreateDate, 101) >= CONVERT(varchar, cte.date, 101)
GROUP BY CTE.DATE
you can get the result using case based aggregation
The CTE generates list of dates for a given range.
For each day, total active ( created that day and created previously but not resolved) and total resolved that day are calculated using case, max and group by
declare #start_date datetime = '2014-11-10'
declare #end_date datetime ='2014-11-13'
;WITH CTE AS
(
SELECT #start_date AS date
UNION ALL
SELECT DATEADD(day, 1, date) as date
FROM CTE
WHERE DATEADD(day, 1, date) <= #end_date
)
select cte.date,
sum( case when createDate <= cte.date and ( resolveddate is null or ResolvedDate >= cte.date) then 1 else 0 end
) as TotalActive,
sum( case when cte.date = ResolvedDate then 1 else 0 end
) as TotalResolved
from cte
left join Table1 T
ON T.createDate <= cte.date
GROUP BY CTE.DATE

How to build this sql query

i want to find the records in sql
from say 25-08-2012 to 01-09-2012
and i want to group by date
here is my query
SELECT CONVERT(VARCHAR(10), date, 105) AS dt,
COUNT(id) AS cnt
FROM tablename
WHERE date BETWEEN CONVERT(DATETIME, '21-08-2012 00:00:00:000',103)
AND CONVERT(DATETIME, '01-09-2012 23:59:00:000' ,103)
GROUP BY CONVERT(VARCHAR(10), date, 105)
i am getting result as
dt cnt
01-09-2012 48
27-08-2012 1
28-08-2012 3
29-08-2012 11
30-08-2012 3
but expect it as
dt cnt
25-08-2012 0
26-08-2012 0
01-09-2012 48
27-08-2012 1
28-08-2012 3
29-08-2012 11
30-08-2012 3
How i can modify above query
i also tried with CASE but no luck
Many Thanks..
The reason you are missing these dates in result is that there's no data for them in your table, however, the following would insure you are getting all of the dates in specified range:
CREATE TABLE #tmp_dates ([date] datetime)
DECLARE #dt_start datetime, #dt_end datetime, #dt_dif int
SET #dt_start = CONVERT(DATETIME, '21-08-2012 00:00:00:000',103)
SET #dt_end = CONVERT(DATETIME, '01-09-2012 23:59:00:000' ,103)
SET #dt_dif = datediff(day,#dt_start,#dt_end)
WHILE #dt_dif >= 0 BEGIN
INSERT INTO #tmp_dates
SELECT dateadd(day,#dt_dif,#dt_start)
SET #dt_dif = #dt_dif - 1
END
SELECT CONVERT(VARCHAR(10), t2.[date], 101) AS dt, COUNT(t1.id) AS cnt
INTO #tmp_result
FROM tablename t1
RIGHT OUTER JOIN #tmp_dates t2
ON CONVERT(VARCHAR(10), t1.[date], 101) = CONVERT(VARCHAR(10), t2.[date], 101)
GROUP BY CONVERT(VARCHAR(10), t2.[date], 101)
ORDER BY CONVERT(DATETIME,CONVERT(VARCHAR(10), t2.[date], 101)) ASC /* DESC */
SELECT convert(VARCHAR(10),CONVERT(DATETIME,dt),105) as dt,cnt FROM #tmp_result
DROP TABLE #tmp_dates
DROP TABLE #tmp_result
Your query cannot be directly modified to return the data you want. To count the dates in question, there must be records in the target table actually having those dates; in your case, however, the dates are merely parameters in the query. As a result, there is no way to incorporate them into your result set.
You must create a secondary table that includes all the dates for which you want data, and then recharacterize your query as a left outer join from that date table to your target table. This will, in turn, give you the zero counts for the dates present in the "date" table, but absent from the target table.
How about using IsNull()? Let me know if this works.
SELECT CONVERT(VARCHAR(10), date, 105) AS dt,
ISNULL(COUNT(id),0) AS cnt
FROM tablename
WHERE date BETWEEN CONVERT(DATETIME, '21-08-2012 00:00:00:000',103)
AND CONVERT(DATETIME, '01-09-2012 23:59:00:000' ,103)
GROUP BY CONVERT(VARCHAR(10), date, 105)