SQL Query Aggregate Error - aggregate-functions

I have written a query to get a list of users who have not logged anytime within the last 45 days. Here's the query I have so far:
SELECT DISTINCT(EMPLOYEE.EMP_CODE),EMP_TIME_DTL.DATE_ENTERED),EMPLOYEE.EMP_LNAME, EMPLOYEE.EMP_FNAME FROM EMP_TIME LEFT JOIN
EMP_TIME_DTL ON EMP_TIME.ET_ID = EMP_TIME_DTL.ET_ID LEFT JOIN
EMPLOYEE ON EMP_TIME.EMP_CODE = EMPLOYEE.EMP_CODE
WHERE MAX(EMP_TIME_DTL.DATE_ENTERED) < DATEADD(day, -45, GETDATE())
GROUP BY EMPLOYEE.EMP_CODE, EMP_TIME_DTL.DATE_ENTERED, EMPLOYEE.EMP_LNAME, EMPLOYEE.EMP_FNAME
The EMP_TIME table contains the hours and the day they worked them. The EMP_TIME_DTL contains the date the employee actually entered the time. That table will have one row for each time entry made. I just want to find: each distinct EMP_CODE for those people who haven't entered time in the last 45 days.
The query I've written will get me those employees who haven't entered time in 45 days, but it also returns all the dates they entered time prior to that 45 day window.
So for example, if the last time John Doe entered time was on MAy 1st, then I want to return that date and his employee id. What I don't want is to return all the time he entered up until May 1st.
I've also tried this:
SELECT DISTINCT(EMPLOYEE.EMP_CODE), (EMP_TIME_DTL.DATE_ENTERED), EMPLOYEE.EMP_LNAME, EMPLOYEE.EMP_FNAME
FROM EMP_TIME LEFT JOIN
EMP_TIME_DTL ON EMP_TIME.ET_ID = EMP_TIME_DTL.ET_ID LEFT JOIN
EMPLOYEE ON EMP_TIME.EMP_CODE = EMPLOYEE.EMP_CODE
GROUP BY EMPLOYEE.EMP_CODE, EMP_TIME_DTL.DATE_ENTERED, EMPLOYEE.EMP_LNAME, EMPLOYEE.EMP_FNAME
HAVING MAX(EMP_TIME_DTL.DATE_ENTERED) < DATEADD(day, -45, GETDATE())
Have also tried:
SELECT MAX(EMP_TIME_DTL.ET_ID), MAX(EMP_TIME_DTL.SEQ_NBR), (EMP_TIME.EMP_CODE), EMPLOYEE.EMP_LNAME, EMPLOYEE.EMP_FNAME, (EMP_TIME_DTL.DATE_ENTERED)
FROM EMP_TIME LEFT JOIN
EMPLOYEE ON EMP_TIME.EMP_CODE = EMPLOYEE.EMP_CODE LEFT JOIN
EMP_TIME_DTL ON EMP_TIME.ET_ID = EMP_TIME_DTL.ET_ID
GROUP BY EMP_TIME.EMP_CODE, EMPLOYEE.EMP_LNAME, EMPLOYEE.EMP_FNAME, (EMP_TIME_DTL.DATE_ENTERED), EMP_TIME_DTL.ET_ID, EMP_TIME_DTL.SEQ_NBR
HAVING MAX(EMP_TIME_DTL.DATE_ENTERED) < DATEADD(day, -45, GETDATE())
ORDER BY EMP_TIME.EMP_CODE, EMPLOYEE.EMP_LNAME, EMPLOYEE.EMP_FNAME, EMP_TIME_DTL.ET_ID, EMP_TIME_DTL.SEQ_NBR, (EMP_TIME_DTL.DATE_ENTERED)
Any help or insight would be greatly appreciated!!

I decided to use the following:
WITH EMP_TIME_CTE
(ET_ID, SEQ_NBR, EMP_CODE, LNAME, FNAME, DATE_ENTERED)
AS
(
SELECT MAX(EMP_TIME_DTL.ET_ID), MAX(EMP_TIME_DTL.SEQ_NBR), (EMP_TIME.EMP_CODE), EMPLOYEE.EMP_LNAME, EMPLOYEE.EMP_FNAME, (EMP_TIME_DTL.DATE_ENTERED)
FROM EMP_TIME LEFT JOIN
EMPLOYEE ON EMP_TIME.EMP_CODE = EMPLOYEE.EMP_CODE LEFT JOIN
EMP_TIME_DTL ON EMP_TIME.ET_ID = EMP_TIME_DTL.ET_ID
WHERE EMPLOYEE.EMP_TERM_DATE IS NULL
GROUP BY EMP_TIME.EMP_CODE, EMPLOYEE.EMP_LNAME, EMPLOYEE.EMP_FNAME, (EMP_TIME_DTL.DATE_ENTERED), EMP_TIME_DTL.ET_ID, EMP_TIME_DTL.SEQ_NBR
HAVING MAX(EMP_TIME_DTL.DATE_ENTERED) < DATEADD(day, -45, GETDATE())
-- ORDER BY EMP_TIME.EMP_CODE, EMPLOYEE.EMP_LNAME, EMPLOYEE.EMP_FNAME, EMP_TIME_DTL.ET_ID, EMP_TIME_DTL.SEQ_NBR, (EMP_TIME_DTL.DATE_ENTERED)
)
SELECT DISTINCT(EMP_CODE), FNAME + ' ' + LNAME AS FULL_NAME, MAX(DATE_ENTERED) AS DATE_ENTERED
from EMP_TIME_CTE
GROUP BY EMP_CODE, FNAME, LNAME
HAVING MAX(DATE_ENTERED) < DATEADD(day, -45, GETDATE())
ORDER BY EMP_CODE asc

Related

Return 0 if the date for a certain day does not have values

I'm doing a query to return the number of count records for a certain date.
The problem is when I use the GroupBy by a certain day, If the date have no records then the date for that day will not be shown in the output.
How can I achieve that?
I'm doing something like:
SELECT COUNT(History.Id)
FROM History
INNER JOIN User ON User.Id = History.UserId
WHERE (#StartDate = #NullDate OR History.CreatedOnDate >= #StartDate)
AND (#EndDate = #NullDate OR History.CreatedOnDate <= #EndDate)
GROUP BY History.CreatedOnDat
Example
01-08, 3 records
02-08, 2 records
04-08, 5 records
I need to have 03-08 with 0 records.
Create a temp table with one day per row:
Declare #StartDate datetime = '2016-08-01'
Declare #EndDate datetime = '2016-08-31'
declare #temp table
(
oneday datetime
);
WHILE #StartDate <= #EndDate
begin
INSERT INTO #temp VALUES (#StartDate);
SET #StartDate = Dateadd(Day,1, #StartDate);
end
select * from #temp
Then, simply join your query with this temp table.

I want to create a reminder of records in asp of before 4 months from today's date in SQL Server

I have written this query :
SELECT
MemberId
,Title
,LastName
,FirstName
,MiddleName
,Occupation
,Productof
,Dateofpurchase
,Dateofservice
,Address
,City
,Pin
,Phone
,MobileNo1
,Email
FROM
tbmMember
WHERE
Dateofservice <= DATEADD(MONTH, - 4, GETDATE())
but this query returning all the records of before 4 months.
Try this, it return before 4 month data from today
WHERE Dateofservice >= DATEADD(MONTH,-4,GETDATE())
This is time (hours, minute,...) sensitive:
SELECT MemberId,Title,LastName,FirstName,MiddleName,Occupation,Productof,Dateofpurchase,Dateofservice,Address,City,Pin,Phone,MobileNo1,Email
FROM tbmMember
WHERE Dateofservice >= DATEADD(MONTH,-4,GETDATE())
AND Dateofservice <= GETDATE()
This one is not time sensitive:
SELECT MemberId,Title,LastName,FirstName,MiddleName,Occupation,Productof,Dateofpurchase,Dateofservice,Address,City,Pin,Phone,MobileNo1,Email
FROM tbmMember
WHERE Dateofservice >= CONVERT(date, DATEADD(MONTH,-4,GETDATE()))
AND Dateofservice <= CONVERT(date, GETDATE())
Assuming Dateofservice is date type.
------------- EDIT -----------------
If you just needs the data of 4 months back:
SELECT MemberId,Title,LastName,FirstName,MiddleName,Occupation,Productof,Dateofpurchase,Dateofservice,Address,City,Pin,Phone,MobileNo1,Email
FROM tbmMember
WHERE Dateofservice = CONVERT(date, DATEADD(MONTH,-4,GETDATE()))
Note that DateofService must be date type, otherwise you need to convert that as date by CONVERT(date, Dateofservice) as well
If you simply want to compare the date of your records with a date four months back from today's date then here is how you can achieve it:
SELECT
MemberId
,Title
,LastName
,FirstName
,MiddleName
,Occupation
,Productof
,Dateofpurchase
,Dateofservice
,Address
,City
,Pin
,Phone
,MobileNo1
,Email
FROM
tbmMember
WHERE
CONVERT(Date,Dateofservice) = CONVERT(Date, DATEADD(MONTH, - 4, GETDATE()))

How to get Data from April To Present Date in SQL

I am working on financial domain. So I want data from April To May.
Suppose Current Month IS June then I only want April to June of this year and it should group by year and month.
And If Suppose Current Month is February then I want details from last April to Jan i.e. April-2013 to Jan-2014
I have got the solution through CTE If i only run CTE Part of the query it is working perfectly fine
This Part of query..
DECLARE #CurrentDate AS datetime = getdate();
DECLARE #FirstDayInCurrentMonth AS datetime = DATEADD(day, 1 - DATEPART(day, #CurrentDate), #CurrentDate);
DECLARE #LastApril AS datetime = DATEADD(month, -(DATEPART(month, #FirstDayInCurrentMonth) + 8) % 12, #FirstDayInCurrentMonth);
WITH Periods AS (
SELECT #LastApril AS [Period]
UNION ALL
SELECT DATEADD(month, 1, [Period])
FROM Periods
WHERE [Period] < #FirstDayInCurrentMonth
)
SELECT
DATENAME(month, [Period]),
DATEPART(year, [Period]),
FROM Periods
But I want sm.is_approved cloumn also work as above query. when I jon other table with above CTE expression. I want proper group by of sm.is_approved column.
I only have the doubt that what will be the condion for joining the other table.
Please give men the proper condition for the below bold part of the query.
DECLARE #CurrentDate AS datetime = getdate();
DECLARE #FirstDayInCurrentMonth AS datetime = DATEADD(day, 1 - DATEPART(day, #CurrentDate), #CurrentDate);
DECLARE #LastApril AS datetime = DATEADD(month, -(DATEPART(month, #FirstDayInCurrentMonth) + 8) % 12, #FirstDayInCurrentMonth);
WITH Periods AS (
SELECT #LastApril AS [Period]
UNION ALL
SELECT DATEADD(month, 1, [Period])
FROM Periods
WHERE [Period] < #FirstDayInCurrentMonth
)
SELECT
DATENAME(month, [Period]),
DATEPART(year, [Period]),
MONTH(sm.is_approved) as [MONTH],
isnull(sum(ISM.selling_price * siim.qty),0) as Price,
isnull(sum(((tm.tax_amount*(ism.selling_price * siim.qty))/100)),0) as Tax,
isnull(sum((ism.selling_price * siim.qty) + (((tm.tax_amount*(ism.selling_price * siim.qty))/100))),0) as TotalPrice
FROM Periods
**LEFT OUTER JOIN RS_Sell_Order_Master as SM on sm.is_approved >= DATEADD(MM, 1, #LastApril)**
left outer join RS_Sells_Invoice_Info_Master as SIIM on sm.sell_order_no = SIIM.sell_order_no
left outer join RS_Inventory_Selling_Master as ISM on ISM.selling_product_id = SIIM.selling_product_id
left outer join RS_Tax_Master as TM on Tm.tax_id = SIIM.tax_id
group by
DATENAME(month, [Period]),
DATEPART(year, [Period]),
MONTH(sm.is_approved)
Can anyone tell me that how to what will be the condition for above query ie bold part of the above query
ie this part I only want this condtion to be true
LEFT OUTER JOIN RS_Sell_Order_Master as SM on sm.is_approved >= DATEADD(MM, 1, #LastApril)
I tried to understand your question, but I'm not sure if I understood :
CTE retrieves all months since last April and you want to display informations linked to RS_Sell_Order_Master (Invoices, Inventory and Taxes...). This should mean, you have to display for all months since last April thoses details.
So maybe you just simply need to make match Periods CTE months and years with RS_Sell_Order_Master months and years.
So you just simply needs to do that :
FROM Periods as P
left outer join RS_Sell_Order_Master as SM
on MONTH(sm.is_approved) = MONTH(P.[Period])
and YEAR(sm.is_approved) = YEAR(P.[Period])
Here in the full code :
DECLARE #CurrentDate AS datetime = getdate();
DECLARE #FirstDayInCurrentMonth AS datetime = DATEADD(day, 1 - DATEPART(day, #CurrentDate), #CurrentDate);
DECLARE #LastApril AS datetime = DATEADD(month, -(DATEPART(month, #FirstDayInCurrentMonth) + 8) % 12, #FirstDayInCurrentMonth);
WITH Periods AS (
SELECT #LastApril AS [Period]
UNION ALL
SELECT DATEADD(month, 1, [Period])
FROM Periods
WHERE [Period] < #FirstDayInCurrentMonth
)
SELECT
DATENAME(month, [Period]),
DATEPART(year, [Period]),
MONTH(sm.is_approved) as [MONTH],
isnull(sum(ISM.selling_price * siim.qty),0) as Price,
isnull(sum(((tm.tax_amount*(ism.selling_price * siim.qty))/100)),0) as Tax,
isnull(sum((ism.selling_price * siim.qty) + (((tm.tax_amount*(ism.selling_price * siim.qty))/100))),0) as TotalPrice
FROM Periods as P
left outer join RS_Sell_Order_Master as SM
on MONTH(sm.is_approved) = MONTH(P.[Period])
and YEAR(sm.is_approved) = YEAR(P.[Period])
left outer join RS_Sells_Invoice_Info_Master as SIIM
on sm.sell_order_no = SIIM.sell_order_no
left outer join RS_Inventory_Selling_Master as ISM
on ISM.selling_product_id = SIIM.selling_product_id
left outer join RS_Tax_Master as TM
on Tm.tax_id = SIIM.tax_id
group by
DATENAME(month, [Period]),
DATEPART(year, [Period]),
MONTH(sm.is_approved)
If i'm wrong correct me, or if you have another issue just leave a comment.
I am not sure, but seeing at the tables I think your joins should be as follows:
FROM Periods
LEFT OUTER JOIN RS_Sell_Order_Master as SM on sm.is_approved >= DATEADD(MM, 1, #LastApril)
INNER join RS_Sells_Invoice_Info_Master as SIIM on sm.sell_order_no = SIIM.sell_order_no
INNER join RS_Inventory_Selling_Master as ISM on ISM.selling_product_id = SIIM.selling_product_id
INNER join RS_Tax_Master as TM on Tm.tax_id = SIIM.tax_id
And Grouping as:
GROUP BY
DATEPART(year, [Period]),
DATENAME(month, [Period]),
MONTH(sm.is_approved)
Try the code below instead of your first three lines, I basically turned the date into a Date without the time which will probably join onto your periods table properly
DECLARE #CurrentDate AS datetime = CAST(FLOOR(CAST(getdate() AS FLOAT)) AS DATETIME)
DECLARE #FirstDayInCurrentMonth AS datetime = DATEADD(day, 1 - DATEPART(day, #CurrentDate), #CurrentDate)
DECLARE #LastApril AS datetime = DATEADD(month, -(DATEPART(month, #FirstDayInCurrentMonth) + 8) % 12, #FirstDayInCurrentMonth)
first you have to compare between dates e.g. compare Feb-2014 and Apr-2014 if false the you have to subtract one from the year part of April.
You can use functions to compare and substring the date and subtract the date.
First thing, the way you generate dates, you should remove the Hour part using:
DATEADD(hour, 0, DATEDIFF(DAY, 0,#CurrentDate))
Second, try using Inner Join instead of left join.
Still I would suggest you give us better idea of how the data is stored. Possibly add the basic schema and test values in the SQL Fiddle
So I can execute the query and get better idea of what you want.

How to get last six month's data in sql

I am developing one chart in that chart I want to show last six month's details separately.
I want to show the details in bar chart.
But I am not getting the any solution.
I am bit weak in sql queries.
Till now I got the data for last month.
But I want the data for last six month.
here's my code.
DECLARE #StartDate DATETIME, #EndDate DATETIME
SET #StartDate = DATEADD(mm, DATEDIFF(mm,0,getdate())-1, 0)
SET #EndDate = DATEADD(mm, 1, #StartDate)
SELECT sum(quantity)
FROM RS_Sell_Order_Master as s
left outer join RS_Sell_Order_Mapping as sm on sm.sell_order_no = s.sell_order_no
left outer join RS_GIN_Master as GIN on gin.product_id = sm.product_id
WHERE del_date BETWEEN #StartDate AND #EndDate
I want o/p of last six month like this suppose I have sell 10 quantity last month & 20 prevous to that month & I didnt sell before that So o/p should be
null
null
null
null
10
20
some thing like this.
This will assign a date exactly 6 months ago - there doesn't seem to be a reason why you would need to go back to the zero datum of SqlServer's DATETIME:
SET #StartDate = DATEADD(mm, -6, CURRENT_TIMESTAMP);
Edit
Assuming that you want month's aligned from the first to the end of each month,
and assuming because you have nulls but still want to show data that we will need to manufacture the missing months (e.g. with a recursive CTE)
DECLARE #StartDate DATETIME;
SET #StartDate = DATEADD(mm, -6, CURRENT_TIMESTAMP);
WITH cte AS
(
SELECT 0 AS TheMonth
UNION ALL
SELECT TheMonth + 1
FROM cte
WHERE TheMonth < 5
)
SELECT sum(quantity)
FROM
cte
LEFT OUTER JOIN RS_Sell_Order_Master as s
ON del_date >= DATEADD(MM, cte.TheMonth, #StartDate) AND del_date < DATEADD(MM, cte.TheMonth + 1, #StartDate)
-- Other Joins here
GROUP BY cte.TheMonth
ORDER BY cte.TheMonth;
SqlFiddle here
total no of items per month can be calculated like
select sum(items),left(date,6)+'01' from yourTable
group by left(date,6)
assuming your date is in 112 format....and it is of varchar(8) type..

How to select top rated photos in the last few days?

Here is my data context:
Photos (ID, Title)
Users (ID, FullName)
Ratings (PhotoID, UserID, Value, Date)
Business rules:
users can rate a photo from 1 to 5
a given user can rate a given photo only once
I want to select the top rated photos by day in the last let's say 3 days. So which photo got the best rating today, yesterday and the day before yesterday? I would like to make the number of days variable if it possible. I have to display the last N days only they rated excluding empty days.
I would like to get the photos in a single query/result because I want to bind it to a ListView to display them on a web form.
I've started this way:
DECLARE #days INT = 3
SELECT TOP (#days) ... FROM Ratings
INNER JOIN Photos ON Photos.ID = Ratings.PhotoID
GROUP BY DATEDIFF(day, [Date], CURRENT_TIMESTAMP)
ORDER BY DATEDIFF(day, [Date], CURRENT_TIMESTAMP) DESC
How can I group my groups by PhotoID, order them by SUM(Value) and select the first one from each group? Thank you very much for your help.
SELECT Date, TotalRating, Photos.*
FROM Photos
INNER JOIN
(SELECT ROW_NUMBER() OVER (ORDER BY Date DESC) AS RowNumber,
PhotoID, Date, TotalRating
FROM (SELECT ROW_NUMBER() OVER (PARTITION BY Date, ORDER BY TotalRating DESC) AS inRowNumber,
PhotoID, Date, TotalRating
FROM (SELECT PhotoID, Date, SUM(Value) AS TotalRating
FROM Photos
GROUP BY PhotoID, Date
HAVING SUM(Value) > 0 ) t)
WHERE inRowNumber = 1) t ON Photos.Id = t.PhotoID
WHERE RowNumber <= #days

Resources