Как получить номер строки или идентификатор того, где было найдено значение MAX () - PullRequest
0 голосов
/ 09 июня 2019

Добрый день, сообщество. Я с трудом пытаюсь найти способ достичь результатов, которые я пытаюсь получить. Поскольку я не очень хорошо разбираюсь в SQL-запросах, я начинаю сходить с ума. Я пытаюсь найти наивысшую и наименьшую оценку в конкретном тесте, но я также хочу получить идентификатор или номер строки (они совпадают) для строк, в которых были MAX () и MIN () найденный.

Таблица «Результаты» выглядит так:

 ResultID|Test_UK|Test_US|TestUK_Scr|TestUS_Scr|TestTakenOn
   1         1       3      85          14     2018-11-22 00:00:00.000
   2         3       1      41          94     2018-11-23 00:00:00.000
   3         2       4      71          54     2018-11-24 00:00:00.000
   4         4       2      51          52     2018-12-25 00:00:00.000
   5         6       3      74          69     2018-12-01 00:00:00.000
   6         3       6      83          57     2018-12-02 00:00:00.000
   7         7       4      91          98     2018-12-03 00:00:00.000
   8         4       7      88          22     2018-12-04 00:00:00.000
   9         5       8      41          76     2018-12-08 00:00:00.000
   10        8       5      37          64     2018-12-09 00:00:00.000

Результаты, которые я получаю при выполнении запроса ...

TestID|TopScore|LowScore|LastDateTestTaken
   1      94       85    2018-11-23 00:00:00.000
   2      71       52    2018-11-25 00:00:00.000
   3      83       14    2018-12-02 00:00:00.000
   4      98       51    2018-12-04 00:00:00.000
   5      64       41    2018-12-09 00:00:00.000
   6      74       57    2018-12-02 00:00:00.000
   7      91       22    2018-12-04 00:00:00.000
   8      76       37    2018-12-09 00:00:00.000

Это запросы, над которыми я работаю.

Этот запрос возвращает результаты, упомянутые выше

WITH
-- Combine the results of UK and US tests
    Combined_Results_Both_Tests AS(
                select ResultID as resultID, Test_UK as TestID, Test_UK_Scr as TestScore, TestTakenOn as TestDate from Results
                union all 
                select ResultID as resultID, Test_US as TestID, Test_US_Scr as TestScore, TestTakenOn as TestDate from Results),
--Gets TOP and WORST results of the tests, LastDateTaken (Needs to add ResultID!)
    Get_Best_and_Worst_Results_And_LastTestDate AS(
                SELECT TestID ,max(TestScore) AS TopScore ,min(TestScore) AS LowScore ,max(TestDate) AS LastDateTestTaken
                FROM Combined_Results_Both_Tests
                GROUP BY TestID)
--Final query execution
SELECT * FROM Get_Best_and_Worst_Results_And_LastTestDate

Я пытался достичь желаемых результатов с помощью чего-то подобного, что не работает, а также очень неэффективно. Я имею в виду, что он не работает, он заполнен дубликатами, когда совпадение найдено в тестах США и Великобритании.

--Gets ReslutID of Min and Max values
    Get_ResultID_Of_Results AS(
                SELECT * FROM Get_Best_and_Worst_Results_And_LastTestDate A
                CROSS APPLY
                (SELECT ResultID FROM Results res
                WHERE   (A.TestID = res.Test_UK AND A.TopScore = res.Test_UK_Scr) OR
                        (A.TestID = res.Test_US AND A.TopScore = res.Test_UK_Scr) OR
                        (A.TestID = res.Test_UK AND A.LowScore = res.Test_UK_Scr) OR
                        (A.TestID = res.Test_US AND A.LowScore = res.Test_UK_Scr) OR
                        (A.TestID = res.Test_UK AND A.TopScore = res.Test_US_Scr) OR
                        (A.TestID = res.Test_US AND A.TopScore = res.Test_US_Scr) OR
                        (A.TestID = res.Test_UK AND A.LowScore = res.Test_US_Scr) OR
                        (A.TestID = res.Test_US AND A.LowScore = res.Test_US_Scr)) D)
SELECT * FROM Get_ResultID_Of_Results

Это результаты, которых я пытаюсь достичь (дополнительные столбцы, в которых указывается, где были найдены значения Max и Min), в которых указывается ResultID из таблицы Results. Кроме того, номера строк соответствуют ResultID в таблице.

TestID|TopScore|LowScore|LastDateTestTaken    |MaxValueLocID|MinValueLocID|
   1      94       85    2018-11-23 00:00:00.000       2             1
   2      71       52    2018-11-25 00:00:00.000       3             4
   3      83       14    2018-12-02 00:00:00.000       6             1
   4      98       51    2018-12-04 00:00:00.000       7             4
   5      64       41    2018-12-09 00:00:00.000       10            9
   6      74       57    2018-12-02 00:00:00.000       5             6
   7      91       22    2018-12-04 00:00:00.000       7             8
   8      76       37    2018-12-09 00:00:00.000       9             10

Обращайтесь за любой помощью с решением, теоретическим или даже практическим. Спасибо!

Ответы [ 2 ]

1 голос
/ 09 июня 2019
with allScores (TestId, Score, TestTakenOn, valueLoc) as
(
  select [Test_UK], [TestUK_Scr],[TestTakenOn], ResultId from scores
  union all
  select [Test_US], [TestUS_Scr],[TestTakenOn], ResultId from scores
),
maxMin (TestId, MaxScore, MinScore, LastTestDate) as (
  select TestId, Max(score), Min(score), Max(TestTakenOn)  
  from allScores
  group by TestId
)
select mm.*, a1.valueLoc as MaxValueLoc, a2.ValueLoc as MinValueLoc
from maxMin mm
inner join allScores a1 
on mm.TestId = a1.TestId and mm.MaxScore = a1.score
inner join allScores a2 
on mm.TestId = a2.TestId and mm.MinScore = a2.score;

Демонстрация DBFiddle

1 голос
/ 09 июня 2019

Если я правильно понимаю, вы хотите отключить данные и агрегировать:

select v.testid, max(v.score), min(v.score) max(v.TestTakenOn)
from results r cross apply
     (values (Test_UK, TestUK_Scr, TestTakenOn),
             (Test_US, TestUS_Scr, TestTakenOn)
     ) v(testid, score, TestTakenOn)
group by v.testid;

Затем вы можете изменить это с помощью оконных функций:

select v.testid, max(v.score), min(v.score) max(v.TestTakenOn),
       max(case when seqnum_desc = 1 then resultid end) as resultid_max,
       max(case when seqnum_asc = 1 then resultid end) as resultid_min
from (select r.resultid, v.*,
             row_number() over (partition by v.testid order by v.score asc) as seqnum_asc,
             row_number() over (partition by v.testid order by v.score desc) as seqnum_desc
      from results r cross apply
           (values (Test_UK, TestUK_Scr, TestTakenOn),
                   (Test_US, TestUS_Scr, TestTakenOn)
           ) v(testid, score, TestTakenOn)
     ) v
group by v.testid;
...