I have a SQL Table name Finalmarks and columns are:
RegdNo Subject_code [1VAL] [2VAL2] [3VAL3]
112023221 HPENG221 28 44 30
112023225 HPMAT333 10 20 30
112023226 HPMAT333 55 39 44
112023224 HPEPH333 55 45 65
The required output, row-wise, is as follows:
(28+30)/2=29
(20+30)/2=25
(39+44)/2=42(41.5)
(55+65)/2=60
I have tried these following queries:
First Query
SELECT RegdNo, Subject_code,
ROUND(((CASE WHEN [1VAL] <= [2VAL] AND [1VAL] <= [3VAL] THEN [1VAL]
WHEN [2VAL] <= [1VAL] AND [2VAL] <= [3VAL] THEN [2VAL]
ELSE [3VAL] END) +
(CASE WHEN ([1VAL] >= [2VAL] AND [1VAL] <= [3VAL]) OR ([1VAL] <= [2VAL] AND [1VAL] >= [3VAL]) THEN [1VAL]
WHEN ([2VAL] >= [1VAL] AND [2VAL] <= [3VAL]) OR ([2VAL] <= [1VAL] AND [2VAL] >= [3VAL]) THEN [2VAL]
ELSE [3VAL] END)) / 2, 0) AS FinalMArks
FROM FinalMarks;
According to my desired output, this query has produced correct values for only the first and third rows.
Second Query
SELECT RegdNo, Subject_code,
ROUND(((CASE WHEN [1VAL] >= [2VAL] AND [1VAL] >= [3VAL] THEN [1VAL]
WHEN [2VAL] >= [1VAL] AND [2VAL] >= [3VAL] THEN [2VAL]
ELSE [3VAL] END) +
(CASE WHEN ([1VAL] >= [2VAL] AND [1VAL] <= [3VAL]) OR ([1VAL] <= [2VAL] AND [1VAL] >= [3VAL]) THEN [1VAL]
WHEN ([2VAL] >= [1VAL] AND [2VAL] <= [3VAL]) OR ([2VAL] <= [1VAL] AND [2VAL] >= [3VAL]) THEN [2VAL]
ELSE [3VAL] END)) / 2, 0) AS FinalMArks
FROM FinalMarks;
This query has produced correct values for only the second and fourth rows.
How to combine these two queries for required output?
4条答案
按热度按时间ohfgkhjo1#
Generate all three pairs of values and then rank them according to their differences. Tiebreaker is to sort by the value of the larger number:
With exactly 3 values you can "sort" them using some algebra on aggregate results. You can then easily determine whether the middle value is left or right of the midpoint of the interval. This is mostly for fun although it doesn't require analytic functions, which might make it useful on older systems:
https://dbfiddle.uk/fo5z5hfr
BONUS
Here's a fairly concise expression that also works. It's based on finding the two values that are on the same side of the trio's average. The symmetry in the expression is easier to follow than a long series of inequalities:
atmip9wb2#
It's a lot of typing, but doing the comparisons for every possible variation (and hoping no-one will ask this to be done for more than 3 numbers 😉):
Results:
hkmswyz63#
You can use a combination of LEAST() and GRETEST() functions. Here is a snippet.
Calculate avg of first two vals
Calculate avg of second and third vals
Calculate absolute diff between the first and two averages.
) as subquery;
and finally compare results
I hope this helps.
mwecs4sa4#
Taking the latest available information from the question it seesm you want to average all 3 numbers, then choose the 2 largest values closest to that average, then average the 2 that are chosen. I believe this meets the test cases provided. Note the syntax below works in SQL Server.
fiddle
Here is a different syntax for the same results (for SQL Server):
and that can be used as a lateral join instead of
cross apply
, e.g. in Postgres: