2016-11-07 7 views
0

Я искал и этот сайт, и Google в целом, пытаясь найти решение моей проблемы, но все, что я, похоже, встречаю, это ошибки в моем запросе.MS Access - Delta (change over x) Между текущей и предыдущей строкой

У меня есть таблица под названием «Обзор с полями» Отверстие, глубина, Az, Dip.

Hole Depth Az  Dip 
--------------------------- 
AB1  0  170 -77 
AB1 150  166 -76.5 
AB1 200  160 -75 
AD1  0  350 -88 
AD1 65  344 -87.6 
AD1 89  340 -85.4 
AB2  0  152 -66 
AB2 135  150 -63.2 

Мне нужен запрос, который будет найти изменение аза по глубине (между двумя рядами) и изменение падения по глубине (между двумя рядами), но только для отверстий, которые начинаются с «AB». Таким образом, окончательный результат должен выглядеть примерно так (с одним значением вместо формулы):

Hole Depth DeltaAz   DeltaDip 
------------------------------------------- 
AB1 150  (170-166)/150  (-77--76.5)/150 
AB1 200  (166-160)/50  (-76.5--75)/50 
AB2 135  (152-150)/135  (-66--63.2)/135 

Я пробовал кучу разных возможных запросов, которые я нашел здесь, но ничего не действительно работал. Самое близкое, что я получил, - это простой код ниже, который я использовал для проверки первого шага (получение разницы между двумя строками). Однако, когда он запустится, я увижу результаты и сообщение об ошибке Only one record can be returned by this subquery. Когда я щелкнул по ошибке, все мои результаты исчезли.

SELECT Hole, Depth, [Az] - (
      SELECT TOP 1 Az 
      FROM Survey AS S 
      WHERE Survey.Hole = S.Hole AND S.Az < Survey.Az 
      ORDER BY S.Az DESC 
      ) AS Diff 
FROM Survey 
WHERE (
    SELECT TOP 1 Az 
    FROM Survey AS S 
    WHERE Survey.Hole = S.Hole AND S.Az < Survey.Az 
    ) 
    IS NOT NULL AND Hole LIKE 'AB*' 
ORDER BY Survey.Hole, Depth, Survey.Az 
; 

У кого-нибудь есть решение, чтобы помочь мне? Я использую MS Access 2013.

+0

Есть всегда 3 записи в отверстие, или это переменная величина? – Aron

+0

Это переменная сумма. Это больше похоже на 20-30 записей за отверстие. –

ответ

0

: edit: видимо, у меня нет понимания исследования, а row_number() недоступен в доступе MS, и нет никаких больших альтернатив.

Я не уверен на 100%, что это точно, что вам нужно, и я уверен, что он может быть улучшен, но он должен привести вас в правильном направлении.

Сообщение об ошибке, которое вы получаете, связано с тем, что ваш подзапрос возвращает более одной записи - даже если вы указали «верхний 1», я считаю, что верхнее предложение не обрабатывается до тех пор, пока результат не будет возвращен, и когда подзапрос возвращает более одной записи, он выдает ошибку. Вы можете использовать row_number() для дискретного возврата ОДНОЙ записи (что я и сделал ниже).

Попробуйте онлайн http://rextester.com/RBQ22368

SELECT * 
FROM (
    --Get delta from 0 to 150 
    SELECT s1.hole 
     ,s1.depth 
     ,s1.az 
     ,s1.dip 
     --Create a row number for each hole (each hole starts at 1), ordered by the depth in ascending order (0,150,200 etc) 
     ,row_number() OVER (
      PARTITION BY s1.hole ORDER BY s1.depth 
      ) AS rn 
     ,s1.az - s2.az/(s1.depth - s2.depth) AS DeltaAZ 
     ,convert(DECIMAL(5, 2), s1.dip) - convert(DECIMAL(5, 2), s2.dip)/(s1.depth - s2.depth) AS DeltaDip 
    FROM survey s1 
    INNER JOIN (
     SELECT hole 
      ,depth 
      ,az 
      ,dip 
      ,row_number() OVER (
       PARTITION BY hole ORDER BY depth 
       ) AS rn 
     FROM survey 
     ) s2 
     --Using the same row number calculation as above, we can specific exactly which record to return. Because we have explicitly defined how to calculate the row number, 
     --we know 1 will always be the lowest depth (0), therefore 2 will be the second lowest 
     ON s1.hole = s2.hole 
      AND s2.rn = 1 -- Return the first result, which is the lowest 
    WHERE left(s1.hole, 3) = 'AB1' 
    ) s1 
WHERE s1.rn = 2 --Limit the result to the second highest depth, since that's what you showed on your question (depth = 150) 

--Using the same logic, but different row numbers, run the same result again as a union 
UNION ALL 

SELECT * 
FROM (
    SELECT s2.hole 
     ,s2.depth 
     ,s2.az 
     ,s3.az AS s2az 
     ,s2.dip 
     ,s3.dip AS s2dip 
     ,row_number() OVER (
      PARTITION BY s2.hole ORDER BY s2.depth 
      ) AS rn 
     ,s2.az - s3.az/(s2.depth - s3.depth) AS DeltaAZ 
     ,convert(DECIMAL(5, 2), s2.dip) - convert(DECIMAL(5, 2), s3.dip)/(s2.depth - s3.depth) AS DeltaDip 
    FROM survey s2 
    INNER JOIN (
     SELECT hole 
      ,depth 
      ,az 
      ,dip 
      ,row_number() OVER (
       PARTITION BY hole ORDER BY depth 
       ) AS rn 
     FROM survey 
     ) s3 
     ON s2.hole = s3.hole 
     --This time, we will compare the 3rd result with the second result. 
      AND s3.rn = 2 -- only return the second record 
    ) s2 
WHERE s2.rn = 3 
    AND left(hole, 2) = 'AB' 
ORDER BY s1.hole 
    ,s1.depth