I have a stored procedure like this:
ALTER procedure [dbo].[Driverperformance]
#Ecode nvarchar(50),
#startdate datetime,
#enddate datetime
as
begin
declare #date1 datetime = CONVERT(datetime, #startdate + ' 00:01:00.000', 120);
declare #date2 datetime = CONVERT(datetime, #enddate + ' 23:23:59.000', 120);
SELECT
e.Ecode,CAST(q.dtime AS DATE) as Date,
e.Ename,
count(q.Ecode) CntEcode ,
count(DelEcode) CntDelEcode
FROM EmployeeMaster_tbl e
inner JOIN Transaction_tbl q
ON e.Ecode = q.Ecode where q.Ecode=#Ecode
and dtime between '' + #date1 +'' and ''+#date2+''
group by
e.Ecode,
e.Ename,
CAST(q.dtime AS date)
ORDER BY CAST(q.dtime AS date)--e.Ecode DESC
end
but i am not getting Count of DelEcode proper ,what is wrong with my stored procedure
while i am checking count of DelEcode like this:select * from Transaction_tbl where dtime >='2013-09-03 00:00:00.000' and dtime <='2013-09-03 23:59:59.000' and DelEcode='E003' am getting 35 rows,but while executing the store procedure am getting only 23 counts of CntDelEcode
If you want to count the number of different "DelEcode" try count(distinct DelEcode). If not, you are going to count the number of records with not null DelEcode values. If you perform a join the count will be the result of the cartesian product, not the number of different DelEcodes.
I assume you use SQL Server 2008 or later as you have a CAST(... as date) in your code
There are several issues with your stored procedure:
A weird way to strip time (just cast to date)
A BETWEEN statement that compares strings instead of dates, because of the +'' statements.
Using datetime parameters when you actually need just date
The simplest way would be to rewrite the stored procedure like this
ALTER procedure [dbo].[Driverperformance]
#Ecode nvarchar(50),
#startdate date,
#enddate date
as
begin
SELECT
e.Ecode,CAST(q.dtime AS DATE) as Date,
e.Ename,
count(q.Ecode) AS CntEcode ,
count(DelEcode) AS CntDelEcode
FROM EmployeeMaster_tbl e
inner JOIN Transaction_tbl q
ON e.Ecode = q.Ecode
where q.Ecode=#Ecode
and #startdate <= dtime
and dtime < #enddate
group by
e.Ecode,
e.Ename,
CAST(q.dtime AS date)
ORDER BY CAST(q.dtime AS date)--e.Ecode DESC
end
You shouldn't have problems with code that calls this stored procedure and passes datetime values because the time portions will be truncated. You will encounter problems only if you pass string literals instead of dates, in formats that SQL Server can't identify from your settings
If you have to use datetime parameters in some other part of your stored procedure, you can do a simple cast to date:
ALTER procedure [dbo].[Driverperformance]
#Ecode nvarchar(50),
#startdate datetime,
#enddate datetime
as
begin
declare #date1 date= cast(#startdate as date);
declare #date2 date= cast(#enddate as date);
SELECT
e.Ecode,CAST(q.dtime AS DATE) as Date,
e.Ename,
count(q.Ecode) AS CntEcode ,
count(DelEcode) AS CntDelEcode
FROM EmployeeMaster_tbl e
inner JOIN Transaction_tbl q
ON e.Ecode = q.Ecode
where q.Ecode=#Ecode
and #date1 <= dtime
and dtime < #date2
group by
e.Ecode,
e.Ename,
CAST(q.dtime AS date)
ORDER BY CAST(q.dtime AS date)--e.Ecode DESC
end
You can also get rid of the ORDER BY statement by reordering your GROUP BY. Grouping orders the results, so you can use GROUP BY CAST(q.dtime AS date) , e.Ecode, e.Ename to get your results order by date, Ecode and Ename
Related
I have the following SProc, which works fine for me, but I am trying to create two parameters, to pass in two variables, and I actually have 0 parameters.
ALTER PROCEDURE [dbo].[TimeSeries]
AS
BEGIN
Drop Table UNION_SUMMARY
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
SELECT *
INTO UNION_SUMMARY
FROM
(
Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_TMP_MG_MORTGAGE_SCHED_HIST_SPLIT' AS TBL From TBL_TMP_MG_MORTGAGE_SCHED_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FMDDATA_HIST_SPLIT' AS TBL From TBL_FMDDATA_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_CDARS_HIST_SPLIT' AS TBL From TBL_FR2052A_CDARS_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_OperationalDepositTag_SPLIT' AS TBL From TBL_FR2052A_OperationalDepositTag_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_FXDH_REVAL_HIST_SPLIT' AS TBL From TBL_FR2052A_FXDH_REVAL_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_MULTI_ACCOUNT_HIST_SPLIT' AS TBL From TBL_MULTI_ACCOUNT_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_MULTI_LD_BALANCE_HIST_SPLIT' AS TBL From TBL_MULTI_LD_BALANCE_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_MULTI_LD_HIST_SPLIT' AS TBL From TBL_MULTI_LD_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_SCHD_HIST_SPLIT' AS TBL From TBL_FR2052A_SCHD_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_MULTI_MG_FUTURE_BALANCE_HIST_SPLIT' AS TBL From TBL_MULTI_MG_FUTURE_BALANCE_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_MULTI_MM_HIST_SPLIT' AS TBL From TBL_MULTI_MM_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_TPOS_HIST_SPLIT' AS TBL From TBL_FR2052A_TPOS_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_AGG_BOC_HIST' AS TBL From TBL_FR2052A_AGG_BOC_HIST Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_NB_IU_HIST' AS TBL From TBL_FR2052A_NB_IU_HIST Where AsOfDate Between #StartDate AND #EndDate
) a
END
I would expect to see 2 parameters here, but I see 0.
You need it in the proc declaration...
ALTER PROCEDURE [dbo].[TimeSeries] (#StartDate DATETIME,#EndDate DATETIME)
as...
Because your SP has no parameters. In the context of your Procedure, #StartDate and #EndDate are variables.
To declare a parameter, you need to put them in your CREATE/ALTER clause. For example:
ALTER PROCEDURE [dbo].[TimeSeries] #StartDate datetime, #EndDate datetime AS
BEGIN
DROP TABLE dbo.UNION_SUMMARY;
SELECT *
INTO dbo.UNION_SUMMARY
...
END
The syntax is as follows:
ALTER PROCEDURE [dbo].[TimeSeries]
#StartDate DATETIME,
#EndDate DATETIME
AS
BEGIN
Drop Table UNION_SUMMARY
SELECT *
INTO UNION_SUMMARY
FROM
(
Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_TMP_MG_MORTGAGE_SCHED_HIST_SPLIT' AS TBL From TBL_TMP_MG_MORTGAGE_SCHED_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FMDDATA_HIST_SPLIT' AS TBL From TBL_FMDDATA_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_CDARS_HIST_SPLIT' AS TBL From TBL_FR2052A_CDARS_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_OperationalDepositTag_SPLIT' AS TBL From TBL_FR2052A_OperationalDepositTag_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_FXDH_REVAL_HIST_SPLIT' AS TBL From TBL_FR2052A_FXDH_REVAL_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_MULTI_ACCOUNT_HIST_SPLIT' AS TBL From TBL_MULTI_ACCOUNT_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_MULTI_LD_BALANCE_HIST_SPLIT' AS TBL From TBL_MULTI_LD_BALANCE_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_MULTI_LD_HIST_SPLIT' AS TBL From TBL_MULTI_LD_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_SCHD_HIST_SPLIT' AS TBL From TBL_FR2052A_SCHD_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_MULTI_MG_FUTURE_BALANCE_HIST_SPLIT' AS TBL From TBL_MULTI_MG_FUTURE_BALANCE_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_MULTI_MM_HIST_SPLIT' AS TBL From TBL_MULTI_MM_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_TPOS_HIST_SPLIT' AS TBL From TBL_FR2052A_TPOS_HIST_SPLIT Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_AGG_BOC_HIST' AS TBL From TBL_FR2052A_AGG_BOC_HIST Where AsOfDate Between #StartDate AND #EndDate
Union Select AsOfDate,Portfolio,PID,Reportable_Amount,'TBL_FR2052A_NB_IU_HIST' AS TBL From TBL_FR2052A_NB_IU_HIST Where AsOfDate Between #StartDate AND #EndDate
) a
END
Here i'm Trying to create stored procedure.. group by detepart..is it correct or wrong.??
CREATE PROCEDURE sp_NewvsOldOrders
(
#StartDate DATETIME,
#EndDate DATETIME
)
AS BEGIN
DECLARE #NewCount INT
, #NewRevenue INT
, #NewDate DATETIME
SELECT
#NewDate = DATEPART(DAY, od.OrderDate)
, #NewCount = COUNT(*)
, #NewRevenue = SUM((CONVERT(DECIMAL(18, 2), od.TotalAmount)))
FROM orderdetails od
INNER JOIN customer c
ON od.customerid = c.customerid
WHERE (CONVERT(DATETIME, (CONVERT(VARCHAR(50), od.orderdate, 101))) BETWEEN #StartDate AND #EndDate)
AND ((CONVERT(DATETIME, (CONVERT(VARCHAR(50), od.orderdate, 101)))) = (CONVERT(DATETIME, (CONVERT(VARCHAR(50), c.registereddate, 101)))))
AND (od.TransactionId IS NOT NULL)
AND (od.TransactionId <> '')
GROUP BY DATEPART(DAY, od.OrderDate)
, od.OrderDate
END
Perhaps this is how your stored procedures should be. As you didn't explain your requirement, i can really tell what you are trying to achieve
CREATE PROCEDURE sp_NewvsOldOrders
(
#StartDate DATETIME,
#EndDate DATETIME
)
AS BEGIN
-- not used
--DECLARE #NewCount INT
-- , #NewRevenue INT
-- , #NewDate DATETIME
SELECT
NewDate = DATEPART(DAY, od.OrderDate)
, NewCount = COUNT(*)
, NewRevenue = SUM((CONVERT(DECIMAL(18, 2), od.TotalAmount)))
FROM orderdetails od
INNER JOIN customer c
ON od.customerid = c.customerid
WHERE (od.orderdate >= StartDate)
AND (od.orderdate < DATEADD(DAY, 1, #EndDate))
AND (CONVERT(VARCHAR(50), od.orderdate, 101)
= CONVERT(DATETIME, c.registereddate, 101))
AND (od.TransactionId IS NOT NULL)
AND (od.TransactionId <> '')
GROUP BY DATEPART(DAY, od.OrderDate)
--, od.OrderDate
END
How can I list all dates between two date parameters in SQL Server, without creating a stored procedure, calendar table or recursive function?
There's always the recursive CTE option:
DECLARE #STARTDATE DATETIME
DECLARE #ENDDATE DATETIME
SET #STARTDATE = '2015-01-01'
SET #ENDDATE = '2015-12-31'
;WITH DATE_RANGE (DATES) AS (
SELECT DATEADD(DAY, DATEDIFF(DAY, 0, #STARTDATE), 0)
UNION ALL SELECT DATEADD(DAY, 1, DATES)
FROM DATE_RANGE
WHERE DATEADD(DAY, 1, DATES) <= #ENDDATE)
SELECT DATES
FROM DATE_RANGE
OPTION (MAXRECURSION 0)
Be sure to use the MAXRECURSION option, or your results will be limited to 100 as default.
This uses Row_Number on the spt_values table in Master database to create a list of years, months and dates within the date range.
This is then built into a datetime field, and filtered to only return dates within the date parameters entered.
Very quick to execute and returns 500 years worth of dates (182987 days) in less than 1 second.
Declare #DateFrom datetime = '2000-01-01'
declare #DateTo datetime = '2500-12-31'
Select
*
From
(Select
CAST(CAST(years.Year AS varchar) + '-' + CAST(Months.Month AS varchar) + '-' + CAST(Days.Day AS varchar) AS DATETIME) as Date
From
(select row_number() over(order by number) as Year from master.dbo.spt_values) as Years
join (select row_number() over(order by number) as Month from master.dbo.spt_values) as Months on 1 = 1
join (select row_number() over(order by number) as Day from master.dbo.spt_values) as Days on 1 = 1
Where
Years.Year between datepart(year,#DateFrom) and datepart(year,#DateTo)
and Months.Month between 1 and 12
and
Days.Day between 1 and datepart(day,dateadd(day,-1,dateadd(month,1,(CAST(CAST(Years.Year AS varchar)+'-' + CAST(Months.Month AS varchar) + '-01' AS DATETIME)))))
) as Dates
Where Dates.Date between #DateFrom and #DateTo
order by 1
Following will be a solution for YOU
DECLARE #DATE1 DATE
DECLARE #DATE2 DATE
SET #DATE1 ='20020101'
SET #DATE2 = '20020311'
SELECT #DATE1 as t
into #FromDate
DECLARE cur CURSOR FOR
SELECT t FROM #FromDate
OPEN cur
FETCH NEXT FROM cur INTO #DATE1
WHILE(##FETCH_STATUS=0)
BEGIN
IF(#DATE1<=#DATE2)
INSERT INTO #FromDate
VALUES(DATEADD(DAY,1,#DATE1))
FETCH NEXT FROM cur INTO #DATE1
END
CLOSE cur
DEALLOCATE cur;
SELECT t FROM #FromDate;
DROP TABLE #FromDate;
Simple result.
DECLARE #DATE1 DATE
DECLARE #DATE2 DATE
SET #DATE1 ='20020101'
SET #DATE2 = '20020311'
WHILE(#DATE1<=#DATE2)
Begin
PRINT #DATE1
set #DATE1 = DATEADD(dd,1,#DATE1)
END
I'm trying to write a function to return the number of working days between 2 dates. I have a table with all the bank holidays in which has two fields: BHID and BHDate.
I've written the following SELECT query to test out my theory and it works nicely:
DECLARE #StartDate AS Date, #EndDate AS Date
SET #StartDate = '2015-01-01'
SET #EndDate = '2015-07-01'
;WITH CTE AS (
SELECT #StartDate AS StartDate, #EndDate AS EndDate, #StartDate AS DateCalc
UNION ALL
SELECT #StartDate AS StartDate, #EndDate AS EndDate, DATEADD(dd, 1, DateCalc) AS DateCalc FROM CTE
WHERE DATEADD(dd, 1, DateCalc) <= EndDate)
SELECT COUNT(*) AS Days
FROM CTE
LEFT JOIN psd.dbo.LUBankHolidays BH
ON CTE.DateCalc = BH.BHDate
WHERE BHID IS NULL
AND LEFT(DATENAME(dw, DateCalc) ,1) <> 'S'
option (Maxrecursion 0);
But when I try and put it in a function I get some errors around the SET line, it could be me just not being quite as good on functions as the rest of my knowledge or I was wondering whether it was to do with the CTE not having been used ahead of the SET line? Here's my attempt:
CREATE FUNCTION [dbo].[WorkingDays]
(#StartDate AS Date, #EndDate AS Date
)
RETURNS INT
AS
BEGIN
DECLARE #Days AS INT
;WITH CTE AS (
SELECT #StartDate AS StartDate, #EndDate AS EndDate, #StartDate AS DateCalc
UNION ALL
SELECT #StartDate AS StartDate, #EndDate AS EndDate, DATEADD(dd, 1, DateCalc) AS DateCalc FROM CTE
WHERE DATEADD(dd, 1, DateCalc) <= EndDate)
SET #Days =
(SELECT COUNT(*) AS Days
FROM CTE
LEFT JOIN psd.dbo.LUBankHolidays BH
ON CTE.DateCalc = BH.BHDate
WHERE BHID IS NULL
AND LEFT(DATENAME(dw, DateCalc) ,1) <> 'S'
option (Maxrecursion 0);)
RETURN #Days
END
I even tried inserting the result of the INT into a temporary table and then dropping this after setting #Days before then returning #Days but this then results in an error regarding not being allowed to produce temporary tables as part of a function.
Any help would be great, I'm sure it's a small thing but just escaping me currently.
Because a CTE can only be used in a query, rather than using SET to set the variable, use SELECT instead:
SELECT #Days =
(SELECT COUNT(*) AS Days
FROM CTE …
From MSDN:
A CTE must be followed by a single SELECT, INSERT, UPDATE, or DELETE
statement that references some or all the CTE columns.
Worked it out with stuartd's help:
CREATE FUNCTION [dbo].[WorkingDays]
(#StartDate AS Date, #EndDate AS Date
)
RETURNS INT
AS
BEGIN
DECLARE #Days AS INT
;WITH CTE AS (
SELECT #StartDate AS StartDate, #EndDate AS EndDate, #StartDate AS DateCalc
UNION ALL
SELECT #StartDate AS StartDate, #EndDate AS EndDate, DATEADD(dd, 1, DateCalc) AS DateCalc FROM CTE
WHERE DATEADD(dd, 1, DateCalc) <= EndDate)
SELECT #Days =
(SELECT COUNT(*) AS Days
FROM CTE
LEFT JOIN psd.dbo.LUBankHolidays BH
ON CTE.DateCalc = BH.BHDate
WHERE BHID IS NULL
AND LEFT(DATENAME(dw, DateCalc) ,1) <> 'S')
option (Maxrecursion 0);
RETURN #Days
END
Thanks All
Use this function
CREATE FUNCTION [dbo].[WorkingDays]
(#Start_Date AS Date, #end_Date AS Date
)
RETURNS INT
AS
BEGIN
DECLARE #Days AS INT
WITH AllDays
AS ( SELECT #start_date AS [Date], 1 AS [level]
UNION ALL
SELECT DATEADD(DAY, 1, [Date]), [level] + 1
FROM AllDays
WHERE [Date] < #end_date )
SELECT #Days =COUNT(*) AS Days
FROM AllDays
LEFT JOIN psd.dbo.LUBankHolidays BH
ON AllDays.Date= BH.BHDate
WHERE BHID IS NULL
AND LEFT(DATENAME(dw, AllDays.Date) ,1) <> 'S'
RETURN #Days
END
My stored procedure like this:
ALTER procedure [dbo].[Driverperformance]
#Ecode nvarchar(50),
#startdate datetime,
#enddate datetime
as begin
SELECT e.Ecode, CAST(q.dtime AS DATE) as Date , e.Ename, count(q.Ecode) CntEcode
FROM EmployeeMaster_tbl e
JOIN Transaction_tbl q
ON e.Ecode = q.Ecode
where q.Ecode=#Ecode and dtime >= '' + #startdate +'' and dtime <= ''+#enddate +''
group by e.Ecode, e.Ename, CAST(q.dtime AS date)
ORDER BY CAST(q.dtime AS date)--e.Ecode DESC
end
this is working fine.in this i am getting count of [(q.Ecode)] is perferct.i have one more field in transactiontable name(DelEcode).i want to take count of(DelEcode) the same way.sam way means how i am taking count of Ecode like that i have to take count of DelEcode aslos.so what the changes i have to make in my current stored procedure..while executing am getting out put like this: but i want to get one more column cntDelcode in that i want to show count of DelEcode
Something like this gives the user a choice of whether to query ECODE or DELECODE:
ALTER procedure [dbo].[Driverperformance]
#code nvarchar(50),
#startdate datetime,
#enddate datetime,
#test VARCHAR(1)
as
IF #test = 1 BEGIN
SELECT e.Ecode, CAST(q.dtime AS DATE) as Date , e.Ename, count(q.Ecode) CntEcode
FROM EmployeeMaster_tbl e
JOIN Transaction_tbl q
ON e.Ecode = q.Ecode
where q.Ecode=#code and dtime >= '' + #startdate +'' and dtime <= ''+#enddate +''
group by e.Ecode, e.Ename, CAST(q.dtime AS date)
ORDER BY CAST(q.dtime AS date)--e.Ecode DESC
END
ELSE
BEGIN
SELECT e.delEcode, CAST(q.dtime AS DATE) as Date , e.Ename, count(q.delEcode) Cntcode
FROM EmployeeMaster_tbl e
JOIN Transaction_tbl q
ON e.delEcode = q.delEcode
where q.delEcode=#code and dtime >= '' + #startdate +'' and dtime <= ''+#enddate +''
group by e.delEcode, e.Ename, CAST(q.dtime AS date)
ORDER BY CAST(q.dtime AS date)--e.Ecode DESC
END
END
This is untested, but you can see where I am going. The extra input allows the user to choose which field to test on.
You can also run the following code:
ALTER procedure [dbo].[Driverperformance]
#Ecode nvarchar(50),
#startdate datetime,
#enddate datetime,
#test bit=0
as begin
SELECT e.Ecode, CAST(q.dtime AS DATE) as Date , e.Ename, case when #test=1 then count(q.Ecode) else count(q.delCode) end as CntEcode
FROM EmployeeMaster_tbl e
JOIN Transaction_tbl q
ON e.Ecode = q.Ecode
where q.Ecode=#Ecode and dtime >= '' + #startdate +'' and dtime <= ''+#enddate +''
group by e.Ecode, e.Ename, CAST(q.dtime AS date)
ORDER BY CAST(q.dtime AS date)--e.Ecode DESC
end