Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 CASE statement issues

Author  Topic 

julianfraser
Starting Member

19 Posts

Posted - 2005-04-11 : 14:49:14
I'm having real trouble getting this query to work. Basically there is a table called 'LM001_property_listing' which contains a column called 'listing_start'. I want to only select the top 1 record for each 'listing_start' column, ie. selectig only 1 record for each propertyID, but making sure it is the most recent 'listing_start' date. I have done this in the second query, but then the case statement does not work. Is is the result of the case statement that I need, not necessarily the most recent 'listing_start' date.

Any ideas?

Thanks,
Julian.



SELECT p.propertyID, p.title, p.address1, p.address2, p.town, p.postcode, p.price, ppt.price_term, pt.property_term, pty.property_type, lt.listing_type, ss.sale_status,
CASE
WHEN pl.listing_end IS NULL AND pl.listing_start IS NOT NULL THEN 'NEVER'
WHEN pl.listing_end < GETDATE() AND pl.listing_end IS NOT NULL THEN 'EXPIRED'
WHEN pl.listing_end IS NULL AND pl.listing_start IS NULL THEN 'UNPAID'
ELSE CONVERT(varchar(36), pl.listing_end, 9)
END AS 'expires'
FROM LM001_property p
LEFT JOIN LM001_property_price_term ppt ON ppt.price_termID = p.price_termID
LEFT JOIN LM001_property_term pt ON pt.property_termID = p.property_termID
LEFT JOIN LM001_property_type pty ON pty.property_typeID = p.property_typeID
LEFT JOIN LM001_listing_type lt ON lt.listing_typeID = p.listing_typeID
LEFT JOIN LM001_sale_status ss ON ss.sale_statusID = p.sale_statusID
LEFT JOIN LM001_property_listing pl ON pl.propertyID = p.propertyID
WHERE p.userID = 300001
ORDER BY lt.listing_type



SELECT p.propertyID, p.title, p.address1, p.address2, p.town, p.postcode, p.price, ppt.price_term, pt.property_term, pty.property_type, lt.listing_type, ss.sale_status,
(SELECT MAX(pl.listing_start) FROM LM001_property_listing pl WHERE pl.propertyID = p.propertyID) AS 'starts'
FROM LM001_property p
LEFT JOIN LM001_property_price_term ppt ON ppt.price_termID = p.price_termID
LEFT JOIN LM001_property_term pt ON pt.property_termID = p.property_termID
LEFT JOIN LM001_property_type pty ON pty.property_typeID = p.property_typeID
LEFT JOIN LM001_listing_type lt ON lt.listing_typeID = p.listing_typeID
LEFT JOIN LM001_sale_status ss ON ss.sale_statusID = p.sale_statusID
WHERE p.userID = 300001
ORDER BY lt.listing_type

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2005-04-11 : 15:12:42
will this do it?

--replace this:
--LEFT JOIN LM001_property_listing pl ON pl.propertyID = p.propertyID

--with this
LEFT JOIN ( --derived table of most recent listing_start records by propertyid
Select propertyid, max(listing_start) listing_start
From LM001_property_listing a
JOIN LM001_property b
ON a.propertyID = b.PropertyID
Where p.userid = 300001
Group by propertyid
) pl ON pl.propertyID = p.propertyID


EDIT: Hold on that's not quite right. You also need listing_end. just a sec...

I'm not sure if "top 1" works with a correlated sub-query but try this: (it may be too slow too, let me know)

--replace this:
--LEFT JOIN LM001_property_listing pl ON pl.propertyID = p.propertyID

--with this
LEFT JOIN ( --derived table of most recent listing_start records by propertyid
Select top 1 listing_start, listing_end
From LM001_property_listing a
Where propertyID = p.PropertyID
order by listing_start desc
) pl ON pl.propertyID = p.propertyID


Be One with the Optimizer
TG
Go to Top of Page

julianfraser
Starting Member

19 Posts

Posted - 2005-04-12 : 05:12:58
It didn't like it, doesn't like the reference to the table outside of the subquery. Gave this error.

Server: Msg 107, Level 16, State 2, Line 1
The column prefix 'p' does not match with a table name or alias name used in the query.


SELECT p.propertyID, p.title, p.address1, p.address2, p.town, p.postcode, p.price, ppt.price_term, pt.property_term, pty.property_type, lt.listing_type, ss.sale_status
FROM LM001_property p
LEFT JOIN LM001_property_price_term ppt ON ppt.price_termID = p.price_termID
LEFT JOIN LM001_property_term pt ON pt.property_termID = p.property_termID
LEFT JOIN LM001_property_type pty ON pty.property_typeID = p.property_typeID
LEFT JOIN LM001_listing_type lt ON lt.listing_typeID = p.listing_typeID
LEFT JOIN LM001_sale_status ss ON ss.sale_statusID = p.sale_statusID
LEFT JOIN (
Select top 1 listing_start, listing_end
From LM001_property_listing a
Where a.propertyID = p.PropertyID
order by listing_start desc
) pl ON pl.propertyID = p.propertyID
WHERE p.userID = 300001
ORDER BY lt.listing_type
Go to Top of Page

julianfraser
Starting Member

19 Posts

Posted - 2005-04-12 : 06:40:31
I meant this one... still returned this though...

Server: Msg 107, Level 16, State 2, Line 1
The column prefix 'p' does not match with a table name or alias name used in the query.



SELECT p.propertyID, p.title, p.address1, p.address2, p.town, p.postcode, p.price, ppt.price_term, pt.property_term, pty.property_type, lt.listing_type, ss.sale_status,
CASE
WHEN pl.listing_end IS NULL AND pl.listing_start IS NOT NULL THEN 'NEVER'
WHEN pl.listing_end < GETDATE() AND pl.listing_end IS NOT NULL THEN 'EXPIRED'
WHEN pl.listing_end IS NULL AND pl.listing_start IS NULL THEN 'UNPAID'
ELSE CONVERT(varchar(36), pl.listing_end, 9)
END AS 'expires'
FROM LM001_property p
LEFT JOIN LM001_property_price_term ppt ON ppt.price_termID = p.price_termID
LEFT JOIN LM001_property_term pt ON pt.property_termID = p.property_termID
LEFT JOIN LM001_property_type pty ON pty.property_typeID = p.property_typeID
LEFT JOIN LM001_listing_type lt ON lt.listing_typeID = p.listing_typeID
LEFT JOIN LM001_sale_status ss ON ss.sale_statusID = p.sale_statusID
LEFT JOIN (
Select top 1 listing_start, listing_end
From LM001_property_listing a
Where a.propertyID = p.PropertyID
order by listing_start desc
) pl ON pl.propertyID = p.propertyID
WHERE p.userID = 300001
ORDER BY lt.listing_type
Go to Top of Page

mwjdavidson
Aged Yak Warrior

735 Posts

Posted - 2005-04-12 : 07:07:42
Not exactly sure what you want, but this should constrain the listings to just the most recent ones:


SELECT p.propertyID, p.title, p.address1, p.address2, p.town, p.postcode, p.price, ppt.price_term, pt.property_term, pty.property_type, lt.listing_type, ss.sale_status, pl.listing_start as start,
CASE
WHEN pl.listing_end IS NULL AND pl.listing_start IS NOT NULL THEN 'NEVER'
WHEN pl.listing_end < GETDATE() AND pl.listing_end IS NOT NULL THEN 'EXPIRED'
WHEN pl.listing_end IS NULL AND pl.listing_start IS NULL THEN 'UNPAID'
ELSE CONVERT(varchar(36), pl.listing_end, 9)
END AS 'expires'
FROM LM001_property p
LEFT JOIN LM001_property_price_term ppt ON ppt.price_termID = p.price_termID
LEFT JOIN LM001_property_term pt ON pt.property_termID = p.property_termID
LEFT JOIN LM001_property_type pty ON pty.property_typeID = p.property_typeID
LEFT JOIN LM001_listing_type lt ON lt.listing_typeID = p.listing_typeID
LEFT JOIN LM001_sale_status ss ON ss.sale_statusID = p.sale_statusID
LEFT JOIN LM001_property_listing pl
JOIN
(
SELECT
pl2.propertyID,
MAX(pl2.listing_start) AS listing_start
FROM
dbo.LM001_property_listing pl2
GROUP BY
pl2.propertyID
) AS pl2
ON pl.propertyID = pl2.propertyID
AND pl.listing_start = pl2.listing_start
ON pl.propertyID = p.propertyID

WHERE p.userID = 300001
ORDER BY lt.listing_type


Mark
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2005-04-12 : 08:24:31
Mark's solution is the same as my first attempt. It doesn't include both the listing_end and listing_start for the max listing_start by propertyid.

this should do it: (he said hopefully)

--with this
LEFT JOIN ( --derived table of most recent listing records by propertyid
Select a.PropertyID, a.Listing_start, max(a.Listing_end) listing_end
From From LM001_property_listing a
JOIN (--another derived table to get the latest listing_start for each propertyid
Select PropertyID, max(listing_start) listing_start
From LM001_property_listing
group by propertyID
) b
ON a.propertyID = b.PropertyID
and a.listing_start = b.listing_start
Group by a.PropertyID, a.Listing_start
) pl ON pl.propertyID = p.propertyID


The max(Listing_end) and group by is there in case there are multiple listings for the same propertyid/listing_start combination


Be One with the Optimizer
TG
Go to Top of Page

mwjdavidson
Aged Yak Warrior

735 Posts

Posted - 2005-04-12 : 11:02:06
Hi TG
The difference was that, by just constraining the join to LM001_property_listing with a join to the derived table containing the aggregate function, you can then just add listing_start and listing_end from LM001_property_listing to your select statement (or plug them into the case statement).

Mark
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2005-04-12 : 11:07:58
Hi Mark,
Now that you say that, I noticed the additional JOIN criteria (AND pl.listing_start = pl2.listing_start).

That would do it alright. The only possible problem would be if there are multiple listing records for the same propertyid and same listing_start. That would give dupe records in the result. My last attempt should deal with that but hopefully Julian's data doesn't have that situation in which case your solution would be great.

Be One with the Optimizer
TG
Go to Top of Page

mwjdavidson
Aged Yak Warrior

735 Posts

Posted - 2005-04-12 : 11:52:22
You're quite right TG, I was making a wee assumption there!
Anyway, let's hope Julian manages to make some use of our efforts. He seems to have gone a bit quiet!

Mark
Go to Top of Page

julianfraser
Starting Member

19 Posts

Posted - 2005-04-12 : 13:29:36
I'm still here... had my head buried in code all day. Am trying your solutions now. Thanks for all your help.

Julian.
Go to Top of Page

julianfraser
Starting Member

19 Posts

Posted - 2005-04-13 : 08:52:14
TG and Mark, The new query worked great, thanks for that... i'd been scratching my head for hours.

Cheers for the help,
Julian.
Go to Top of Page
   

- Advertisement -