Drop Table

Support Forum for database administrators and web based access to important newsgroups related to databases
Register on Database Support Forum Edit your profileCalendarFind other Database Support forum membersFrequently Asked QuestionsSearch this forum -> 
For Database admins: Free Database-related Magazines Now Free shipping to Texas


Post New Thread










Thread
Author

median query without using function
I have a table (cars) with 3 fields:

VIN, Class, sell_price
101, sports, 10000
102, sports, 11000
103, luxury, 9000
104, sports, 11000
105, sports, 11000
106, luxury, 5000
107, sports, 11000
108, sports, 11000
109, luxury, 9000

i need to write a query that WITHOUT USING A FUNCTION will return the
median selling price for each class of car. result should look like:

Class, Med_Price
luxury, 9000
sports, 11000

thanks to all u SQLers


Report this thread to moderator Post Follow-up to this message
Old Post
uspensky@gmail.com
02-25-06 02:45 PM


Re: median query without using function
>From your sample data it looks like you want the most commonly
occurring price for each vehicle (I thought this was
called the "mode", not the "median").

CREATE TABLE Cars(VIN INT,Class  VARCHAR(10),sell_pri
ce INT)
INSERT INTO  Cars(VIN,Class,sell_
price) VALUES(101, 'sports', 10000)
INSERT INTO  Cars(VIN,Class,sell_
price) VALUES(102, 'sports', 11000)
INSERT INTO  Cars(VIN,Class,sell_
price) VALUES(103, 'luxury', 9000)
INSERT INTO  Cars(VIN,Class,sell_
price) VALUES(104, 'sports', 11000)
INSERT INTO  Cars(VIN,Class,sell_
price) VALUES(105, 'sports', 11000)
INSERT INTO  Cars(VIN,Class,sell_
price) VALUES(106, 'luxury', 5000)
INSERT INTO  Cars(VIN,Class,sell_
price) VALUES(107, 'sports', 11000)
INSERT INTO  Cars(VIN,Class,sell_
price) VALUES(108, 'sports', 11000)
INSERT INTO  Cars(VIN,Class,sell_
price) VALUES(109, 'luxury', 9000)
GO
CREATE VIEW CarNums
AS
SELECT  Class,sell_price,COU
NT(*) as Num
FROM Cars
GROUP BY Class,sell_price

GO

SELECT c1.Class,c1.sell_price AS Med_Price
FROM CarNums c1
INNER JOIN (
SELECT Class,MAX(Num)
FROM CarNums
GROUP BY Class) C2(Class,Num) ON C2.Class=C1.Class
AND C2.Num=C1.Num


Report this thread to moderator Post Follow-up to this message
Old Post
markc600@hotmail.com
02-25-06 02:45 PM


Re: median query without using function
My mistake, you can get the medians using this


CREATE VIEW CarRank
AS
SELECT c1.VIN,
c1.Class,
c1.sell_price,
(SELECT COUNT(*) FROM Cars c2
WHERE c2.Class=c1.Class
AND ((c2.sell_price<c1.sell_price)
OR (c2.sell_price=c1.sell_price AND c2.VIN<=c1.VIN))) as
Rank,
(SELECT COUNT(*) FROM Cars c2
WHERE c2.Class=c1.Class) as MaxRank
FROM Cars c1

GO

SELECT  Class,AVG(sell_price
) AS Med_Price
FROM CarRank
WHERE Rank IN ((MaxRank+1)/2,(MaxRank/2)+1)
GROUP BY Class


Report this thread to moderator Post Follow-up to this message
Old Post
markc600@hotmail.com
02-25-06 02:45 PM


Re: median query without using function
I have a whoel chapter on verious ways to do this in SQL FOR SMARTIES.
Here is one answer.

Median with Characteristic Function

Anatoly Abramovich, Yelena Alexandrova, and Eugene Birger presented a
series of articles in SQL Forum magazine on computing the median (SQL
Forum 1993, 1994). They define a characteristic function, which they
call delta, using the Sybase sign() function. The delta or
characteristic function accepts a Boolean expression as an argument and
returns a 1 if it is TRUE and a zero if it is FALSE or UNKNOWN.

In SQL-92 we have a CASE expression, which can be used to construct the
delta function. This is new to SQL-92, but you can find vendor
functions of the form IF...THEN...ELSE that behave like the condition
expression in Algol or like the question markPcolon operator in C.

The authors also distinguish between the statistical median, whose
value must be a member of the set, and the financial median, whose
value is the average of the middle two members of the set. A
statistical median exists when there is an odd number of items in the
set. If there is an even number of items, you must decide if you want
to use the highest value in the lower half (they call this the left
median) or the lowest value in the upper half (they call this the right
median).

The left statistical median of a unique column can be found with this
query:

SELECT P1.bin
FROM Parts AS P1, Parts AS P2
GROUP BY P1.bin
HAVING SUM(CASE WHEN (P2.bin <= P1.bin) THEN 1 ELSE 0 END)
= (COUNT(*) + 1) / 2;

Changing the direction of the theta test in the HAVING clause will
allow you to pick the right statistical median if a central element
does not exist in the set. You will also notice something else about
the median of a set of unique values: It is usually meaningless. What
does the median bin number mean, anyway? A good rule of thumb is that
if it does not make sense as an average, it does not make sense as a
median.

The statistical median of a column with duplicate values can be found
with a query based on the same ideas, but you have to adjust the HAVING
clause to allow for overlap; thus, the left statistical median is found
by

SELECT P1.weight
FROM Parts AS P1, Parts AS P2
GROUP BY P1.weight
HAVING SUM(CASE WHEN P2.weight <= P1.weight
THEN 1 ELSE 0 END)
>= ((COUNT(*) + 1) / 2)
AND SUM(CASE WHEN P2.weight >= P1.weight
THEN 1 ELSE 0 END)
>= (COUNT(*)/2 + 1);

Notice that here the left and right medians can be the same, so there
is no need to pick one over the other in many of the situations where
you have an even number of items. Switching the comparison operators in
the two CASE expressions will give you the right statistical median.

The author's query for the financial median depends on some Sybase
features that cannot be found in other products, so I would recommend
using a combination of the right and left statistical medians to return
a set of values about the center of the data, and then averaging them,
thus:

SELECT AVG(P1.weight)
FROM Parts AS P1, Parts AS P2
HAVING (SUM(CASE WHEN P2.weight <= P1.weight -- left median
THEN 1 ELSE 0 END)
>= ((COUNT(*) + 1) / 2)
AND SUM(CASE WHEN P2.weight >= P1.weight
THEN 1 ELSE 0 END)
>= (COUNT(*)/2 + 1))
OR (SUM(CASE WHEN P2.weight >= P1.weight  -- right median
THEN 1 ELSE 0 END)
>= ((COUNT(*) + 1) / 2)
AND SUM(CASE WHEN P2.weight <= P1.weight
THEN 1 ELSE 0 END)
>= (COUNT(*)/2 + 1));

An optimizer may be able to reduce this expression internally, since
the expressions involved with COUNT(*) are constants. This entire query
could be put into a FROM clause and the average taken of the one or two
rows in the result to find the financial median. In SQL-89, you would
have to define this as a VIEW and then take the average.

If you have SQL-2005, you can try something like (untested):

SELECT AVG(x),
ROW_NUMBER () OVER (ORDER BY x ASC) AS hi,
ROW_NUMBER () OVER (ORDER BY x DESC) AS lo,
FROM Foobar
WHERE hi IN (lo, lo-1, lo+1);


Report this thread to moderator Post Follow-up to this message
Old Post
--CELKO--
03-01-06 01:29 AM


Re: median query without using function
i don't do homework for college students.


Report this thread to moderator Post Follow-up to this message
Old Post
Doug
03-01-06 01:29 AM


Sponsored Links





Last Thread Next Thread
Post New Thread

Microsoft SQL Server forum archive

Show a Printable Version Email This Page to Someone! Receive updates to this thread
Microsoft SQL Server
Access database support
PostgreSQL Replication
SQL Server ODBC
FoxPro Support
PostgreSQL pgAdmin
SQL Server Clustering
MySQL ODBC
Web Applications with dBASE
SQL Server CE
MySQL++
Sybase Database Support
MS SQL Full Text Search
PostgreSQL Administration
SQL Anywhere support
DB2 UDB Database
Paradox Database Support
Filemaker Database
Berkley DB
SQL 2000/2000i database
ASE Database
Forum Jump:
All times are GMT. The time now is 05:13 AM.

 
Mobile devices forum | Database support forum archive




Copyrights DropTable.com Database Support Forum 2004 - 2006