views:

320

answers:

5

I am displaying a property from the following table given below. Now what i have to do is, find the property in the same location(suppose my property is located in sec-19, match for sec-19 and if none of them found there then search for the entire city) with the following condition that it should be posted 10 days back or if none is posted 10 days back than take result on the basis of 30 days back.

I have the following table(Properties) mentioned below:

ID|Propertyid|Userid|Projectid|..|Price|...|Listing time|...

Now what i want to retrieve from this table is the 'Propertyid' and 'Average Price' of those properties whose listing time is less than 10 days if none of them are less than 10 days then return the result for less than 30 days.

Can anybody help me solving this problem. Thanks in advance.

Or just Any body can answer me without the Location match.

I need to calculate 'Average Price' from the properties posted 10 days ago, if there is no property posted 10 days ago then take it as 30 days ago. Something like this:

Select AVG(Price) As Average_Price from Properties where (DATEDIFF(day,listingtime,getdate())<30 or DATEDIFF(day,listingtime,getdate())<10)

But here i am getting only one Field 'Average Price' and here also i am not putting the check to filter whether it has been posted 10 days ago or 30 days ago. Knidly Recheck and try to solve my problem. Thanks in Advance.

+1  A: 

Con you please post the DDL/DML also

LAzy Dragon
I tried something like this:select Propertyid, listingtime, SUM(Price)/COUNT(PropertyId) as Average_Price from Properties having(DATEDIFF(day,listingtime,getdate())<30 or DATEDIFF(day,listingtime,getdate())<10)but it doesn't work at all... Infact it's a wrong Query but i want to do like the same way????
Sanju
A: 

What you described above means, that if there is 1 property in the last 10 days, then you want to list that single one. Try this: (I use P.age is for simplicity.)

SELECT * FROM properties P  
WHERE  
-- 10 days old records, if any:  
(((select count(1) from properties p1 where p1.age > 10) > 0) AND (P.age > 10))  
OR  
-- 30 days old records, if zero 10-day-old records found:  
(((select count(1) from properties p1 where p1.age > 10) = 0) AND (P.age > 30))  
Dercsár
I need to calculate 'Average Price' from the properties posted 10 days ago, if there is no property posted 10 days ago then take it as 30 days ago.Something like this:Select SUM(Price)/COUNT(PropertyId) As Average_Price from Propertieswhere (DATEDIFF(day,listingtime,getdate())<30 or DATEDIFF(day,listingtime,getdate())<10)But here i am getting only one Field 'Average Price' and here also i am not putting the check to filter whether it has been posted 10 days ago or 30 days ago.Knidly Recheck and try to solve my problem.Thanks in Advance.
Sanju
use SELECT AVG(Price) FROM [the above query] You get a single row with one field because this an average value of many rows. If you want other fields in the result set, you have to get to know how GROUP BY works.
Dercsár
Yes i know how group by criteria works. It needs to take some criteria to group the result. But where there are many fields to be returned than it's not good to use group by, because it will return error.
Sanju
A: 

if you want a list of property IDs, but only a single average price for all of them, life will be simpler if you do more than one query. this sounds like a good case for using a stored procedure. you could do it like this:

  1. pass location into the stored procedure and select from properties where the location matches
  2. insert the results into a temp table with propertyid, listingtime and avgprice (currently empty)
  3. select rows with a DATEDIFF of 10 days. if 0 results, select rows with a DATEDIFF of 30 days
  4. select AVG price from the temp table, filtering on 10 days if there is data. insert that value into each row of the table

you may want to play with changing the order of items 1 and 3 to see which yields better performance.

Nicholai
A: 

Hi, It should be possible to use something like this:

select section, coalesce(select avg(Price) from table iq1 where Listingdate > dateadd(day,-10,getdate()) and oq.section =iq1.section, select avg(price) from table iq2 where Listingdate > dateadd(day,-30,getdate()) and oq.section =iq2.section,0) as averageprice from table oq group by section

A couple of notes: sorry I'm not in front of my pc so I couldn't proof read this and the brackets may be out, but that's the idea in general-use coalesce to either the first criteria and providing there are no records the average should return null and use the second criteria and if that has none finally 0.

The other thing is to use the date add function as above to make the expression SARGable and there able to use indexes.

Hope this helps, Steve

EDIT

Here is the code which I have done basic testing on. It is simple, and will give you first the average for that section for the last 10 days, failing that, the last 30 days for the section, failing that the last 10 days for all sections and failing that the last 30 days for all sections. It will also give an avergageType of 1,2,3 or 4 respectively.

I apologise in advance for the state of the SQL display - I am yet to work out how to format it nicely-and its really late :)

select sectionID,
coalesce (
(select avg(Price) from Prices iq1 where Listingdate > dateadd(day,-10,getdate())
and > oq.sectionID = iq1.sectionID),
(select avg(price) from Prices iq2 where Listingdate > dateadd(day,-30,getdate())
and > oq.sectionID =iq2.sectionID),
(select avg(Price) from Prices iq1 where Listingdate > dateadd(day,-10,getdate())),
(select avg(Price) from Prices iq1 where Listingdate > dateadd(day,-30,getdate())),
0 ) as averageprice,
CASE WHEN (select > avg(Price) from Prices iq1
where Listingdate > dateadd(day,-10,getdate()) and
oq.sectionID = iq1.sectionID) IS NOT NULL THEN 1 ELSE
CASE WHEN (select > avg(price) from Prices iq2
where Listingdate > dateadd(day,-30,getdate()) and
oq.sectionID =iq2.sectionID) IS NOT NULL THEN 2 ELSE
CASE WHEN (select > avg(Price) from Prices iq1
where Listingdate > dateadd(day,-10,getdate())) IS NOT NULL THEN 3 ELSE
CASE WHEN (select > avg(Price) from Prices iq1
where Listingdate > dateadd(day,-30,getdate())) IS NOT NULL THEN 4 ELSE
5 END END END END AS AverageType from Prices oq
where sectionID = @SectionID group by sectionID

MrCraze
Can you elaborate more than this.I hope this time you would be in front of your pc
Sanju
Hi Sanju, sorry for the delay. I updated my answer as I cant fit the script in the comment.
MrCraze
A: 

I spent some time on this and I believe I addressed all of your concerns. I wasn't completely sure of the datatypes of city or location so I used varchar(100) This should address all of your concerns. Please comment if there is a situation that you described that this doesn't solve.

   CREATE PROCEDURE [dbo].[GetRecentlyListedProperties]
(@location varchar(100), @city varchar(100),@propertyID int)
As
Begin
DECLARE @numberOfDays int,
        @propertyCount int, 
        @IsLocation bit -- looking for a location and not a city    
SET @Propertycount = 0
SET @numberOfDays= 10 
-- CHECK TO SEE IF THERE ARE LISTINGS IN THE LAST 10 DAYS IN THE SAME LOCATION
SELECT  @PropertyCount = 
 Count(*) FROM properties where location = @location and DATEDIFF(day,listingtime,GETDATE()) < @numberOFDays
 and PropertyID != @propertyID
If(@PropertyCount = 0)
Begin
-- CHECK TO SEE IF THERE ARE LISTINGS IN THE LAST 10 DAYS IN THE SAME CITY
SELECT  @PropertyCount = Count(*) from properties where city = @city 
        AND DATEDIFF(day,listingtime,GETDATE()) < @numberOFDays
        AND PropertyID != @propertyID   
    IF(@PropertyCount = 0 )
    BEGIN
    SET @NumberOfDays = 30
    -- CHECK TO SEE IF THERE ARE LISTINGS IN THE LAST 30 DAYS IN THE SAME LOCATION
    SELECT  @PropertyCount = COUNT(*) from properties where location = @location 
            AND DATEDIFF(day,listingtime,GETDATE()) < @numberOFDays
            AND PropertyID != @propertyID
        IF(@PropertyCount = 0 )
        BEGIN
        -- CHECK TO SEE IF THERE ARE LISTINGS IN THE LAST 30 DAYS IN THE SAME CITY
        SELECT @PropertyCount = Count(*) from properties where city = @city 
                AND DATEDIFF(day,listingtime,GETDATE()) < @numberOFDays
                AND PropertyID != @propertyID
        END
        ELSE
        SET @IsLocation = 1 --There are properties in the same location in the last 30 days
    END
    ELSE
    SET @IsLocation  = 0 -- There are properties listed int he city in the last 10 days
End
Else
SET @IsLocation = 1
-- This is where the appropriate results are returned. 
IF(@IsLocation = 1)
Begin
SELECT * ,(SELECT AVG(PRICE) as AveragePrice
       FROM PROPERTIES 
       WHERE DATEDIFF(day,listingtime,GETDATE()) < @numberOFDays
         AND Location = @Location
         AND PropertyID != @propertyID)
FROM Properties 
WHERE DATEDIFF(day,listingtime,GETDATE()) < @numberOFDays
      AND Location = @Location
      AND PropertyID != @propertyID
End
ElSE
SELECT * ,(SELECT AVG(PRICE) as AveragePrice
      FROM PROPERTIES 
          WHERE DATEDIFF(day,listingtime,GETDATE()) < @numberOFDays
          AND City = @City
          AND PropertyID != @propertyID)
FROM Properties 
WHERE DATEDIFF(day,listingtime,GETDATE()) < @numberOFDays
      AND City = @City 
      AND PropertyID != @propertyID
End

You may have to change some datatypes for foreign keys for location and city as I used them as varchars.

awright18
Still it is not working...And by the way this is not my requirement!!!I have to find the property in the same location(suppose my property is located in sec-19, match for sec-19 and if none of them found there then search for the entire city) with the following condition that it should be posted 10 days back or if none is posted 10 days back than take result on the basis of 30 days back.
Sanju
I reworked the problem completely if your datatypes and schema names are the same you should be able copy and past this and have it work. The only column names used are listingtime, location, city and propertyid as well as properties for the table.
awright18