D
Douglas J. Steele
How are you calling the function?
James A. Fortune said:יריב החביב said:Hello,
When i use this code on a table it is work,
but when i use it on a query it do'nt.
what should i do for using this code on query ? .....
Function Median (tName As String, fldName As String) As Single
Dim MedianDB As DAO.Database
Dim ssMedian As DAO.Recordset
Dim RCount As Integer, i As Integer, x As Double, y As Double, _
OffSet As Integer
Set MedianDB = CurrentDB()
Set ssMedian = MedianDB.Openrecordset("SELECT [" & fldName & _
"] FROM [" & tName & "] WHERE [" & fldName & _
"] IS NOT NULL ORDER BY [" & fldName & "];")
'NOTE: To include nulls when calculating the median value, omit
'WHERE [" & fldName & "] IS NOT NULL from the example.
ssMedian.MoveLast
RCount% = ssMedian.RecordCount
x = RCount Mod 2
If x <> 0 Then
OffSet = ((RCount + 1) / 2) - 2
For i% = 0 To OffSet
ssMedian.MovePrevious
Next i
Median = ssMedian(fldName)
Else
OffSet = (RCount / 2) - 2
For i = 0 To OffSet
ssMedian.MovePrevious
Next i
x = ssMedian(fldName)
ssMedian.MovePrevious
y = ssMedian(fldName)
Median = (x + y) / 2
End If
If Not ssMedian Is Nothing Then
ssMedian.Close
Set ssMedian = Nothing
End If
Set MedianDB = Nothing
End Function
THANKS A LOT
I offer the following as an alternative method:
In:
http://groups.google.com/group/comp.databases.ms-access/msg/1f2f7b4979f359ef
I cobbled together a non-VBA SQL method for computing a median.
In:
[Median of GROUP BY values]
http://groups.google.com/group/comp.databases.ms-access/msg/7fb6eb508f22fa9d
I extended it to be able to calculate medians of grouped data.
James A. Fortune
(e-mail address removed)
יריב החביב said:Your solution work perfect
is it posible to implement it on a query insted of table ?
in that case, what about the id (autonumber) ?
James A. Fortune said:יריב החביב said:Your solution work perfect
I'm glad you liked it.
is it posible to implement it on a query insted of table ?
in that case, what about the id (autonumber) ?
That's a great question.
Suppose I have the following table:
tblValues
ID AutoNumber
theValue Long
GpName Text
ID theValue GpName
1 738.1 A
2 655.2 A
3 43.4 A
4 8301.9 A
5 644.5 A
6 46.7 A
7 734.1 A
8 93296 B
9 601.8 B
10 59.5 B
11 3.4 B
12 0.08 B
13 609.9 B
14 0.04 C
15 2.8 C
16 55.7 C
17 0.2 C
18 53.5 C
19 2.6 C
20 3.4 C
21 8408.8 C
22 612.5 C
23 56.3 C
24 44.6 C
25 798.2 C
26 740.7 C
27 0.2 C
Then I can create a query to order the information by GpName, not caring
in what order the values or ID numbers are within a GpName:
qryValues:
SELECT ID, theValue, GpName
FROM tblValues
ORDER BY GpName;
!qryValues:
ID theValue GpName
2 655.2 A
3 43.4 A
4 8301.9 A
5 644.5 A
6 46.7 A
7 734.1 A
1 738.1 A
13 609.9 B
8 9329.6 B
9 601.8 B
10 59.5 B
11 3.4 B
12 0.08 B
15 2.8 C
27 0.2 C
16 55.7 C
17 0.2 C
18 53.5 C
19 2.6 C
20 3.4 C
21 8408.8 C
22 612.5 C
23 56.3 C
24 44.6 C 25 798.2 C
26 740.7 C
14 0.04 C
Now I can obtain the Ranking and the WantRanking.
qryRankForMedianFromQuery:
SELECT qryValues.GpName, qryValues.theValue, (SELECT Count(A.theValue)
FROM qryValues AS A WHERE A.theValue > qryValues.theValue AND A.GpName
= qryValues.GpName) + 1 AS Ranking, (SELECT Count(*) FROM qryValues AS A
WHERE A.GpName = qryValues.GpName) / 2 + 0.5 AS WantRanking
FROM qryValues;
!qryRankForMedianFromQuery:
GpName theValue Ranking WantRanking
A 655.2 4 4
A 43.4 7 4
A 8301.9 1 4
A 644.5 5 4
A 46.7 6 4
A 734.1 3 4
A 738.1 2 4
B 609.9 2 3.5
B 9329.6 1 3.5
B 601.8 3 3.5
B 59.5 4 3.5
B 3.4 5 3.5
B 0.08 6 3.5
C 2.8 10 7.5
C 0.2 12 7.5
C 55.7 6 7.5
C 0.2 12 7.5
C 53.5 7 7.5
C 2.6 11 7.5
C 3.4 9 7.5
C 8408.8 1 7.5
C 612.5 4 7.5
C 56.3 5 7.5
C 44.6 8 7.5
C 798.2 2 7.5
C 740.7 3 7.5
C 0.04 14 7.5
That shows that using the values alone for the ranking causes a problem
because the ties can cause the ranking value to stray from the desired
ranking. When the ID was used there was not a possibility of a tie. So
eliminate the tie situation by adding the number of duplicate values
after the current one (ID wise) noting that the ID assignments within a
GpName can be arbitrary.
qryRankForMedianFromQuery:
SELECT qryValues.GpName, qryValues.theValue, (SELECT Count(A.theValue)
FROM qryValues AS A WHERE A.theValue > qryValues.theValue AND A.GpName =
qryValues.GpName) + (SELECT Count(A.theValue) FROM qryValues AS A WHERE
A.theValue = qryValues.theValue AND A.ID < qryValues.ID) + 1 AS Ranking,
(SELECT Count(*) FROM qryValues AS A WHERE A.GpName = qryValues.GpName)
/ 2 + 0.5 AS WantRanking
FROM qryValues;
!qryRankForMedianFromQuery:
GpName theValue Ranking WantRanking
A 655.2 4 4
A 43.4 7 4
A 8301.9 1 4
A 644.5 5 4
A 46.7 6 4
A 734.1 3 4
A 738.1 2 4
B 609.9 2 3.5
B 9329.6 1 3.5
B 601.8 3 3.5
B 59.5 4 3.5
B 3.4 5 3.5
B 0.08 6 3.5
C 2.8 10 7.5
C 0.2 13 7.5
C 55.7 6 7.5
C 0.2 12 7.5
C 53.5 7 7.5
C 2.6 11 7.5
C 3.4 10 7.5
C 8408.8 1 7.5
C 612.5 4 7.5
C 56.3 5 7.5
C 44.6 8 7.5
C 798.2 2 7.5
C 740.7 3 7.5
C 0.04 14 7.5
qryGroupMedians:
SELECT Avg(theValue) AS Median, qryRankForMedianFromQuery.GpName FROM
qryRankForMedianFromQuery WHERE (Abs([Ranking] -
[WantRanking]) < 0.6) GROUP BY qryRankForMedianFromQuery.GpName;
!qryGroupMedians:
Median GpName
655.2 A
330.65 B
49.05 C
Note that with effort it may be possible to simplify the second query.
Also note that a group aggregate function such as DCount can be used in
lieu of a subquery.
James A. Fortune
(e-mail address removed)
DVIR - Jewish nickname for the Holy of Holies -- from an explanation
about the meaning of the name of the Dvir Hotel in Haifa.
יריב החביב said:Thank you Dvir,
you give me appetite to learn sql comprehensivly
The problem is that in my query there isn't id number.
will you recomend to append the query to a table with id number
and from the table to work out the qryRankForMedianFromQuery
and qryGroupMedians ?
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.