2016-11-07 1 views
0

J'ai parcouru ce site et google en général en essayant de trouver une solution à mon problème, mais tout ce que j'ai l'air de rencontrer est une erreur dans ma requête.MS Access - Delta (basculer entre x) entre la ligne actuelle et la ligne précédente

J'ai une table appelée Levé avec les champs Hole, Depth, 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 

je besoin d'une requête qui va trouver le changement de az sur la profondeur (entre deux lignes) et le changement de plongeon de la profondeur (entre deux lignes), mais seulement pour les trous qui commencent par « AB ». Ainsi, le résultat final devrait ressembler à ceci (avec une seule valeur au lieu de la formule):

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 

J'ai essayé un tas de différentes requêtes possibles que je trouve ici, mais rien n'a vraiment fonctionné. Le plus proche que j'ai eu était avec le code simple ci-dessous que j'utilisais pour tester la première étape (obtenir la différence entre deux rangées). Cependant, quand il a couru, je verrais les résultats et un message d'erreur Only one record can be returned by this subquery. Quand j'ai cliqué OK sur l'erreur, tous mes résultats ont disparu.

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 
; 

Est-ce que quelqu'un a une solution pour m'aider? J'utilise MS Access 2013.

+0

Y at-il toujours 3 enregistrements par trou, ou est-il une quantité variable? – Aron

+0

C'est un montant variable. C'est en fait plus comme 20-30 enregistrements par trou. –

Répondre

0

: edit: apparemment, je n'ai pas de compréhension en recherche et row_number() n'est pas disponible en accès MS et il n'y a pas de bonnes alternatives.

Je ne suis pas sûr à 100% que c'est exactement ce dont vous avez besoin, et je suis sûr qu'il pourrait être amélioré, mais il devrait vous aider dans la bonne direction. Le message d'erreur que vous obtenez est parce que votre sous-requête renvoie plus de un enregistrement - même si vous avez spécifié "top 1", je crois que la clause supérieure n'est pas traitée qu'après que le résultat est renvoyé, et lorsqu'une sous-requête renvoie plus d'un enregistrement, elle expire. Vous pouvez utiliser row_number() pour retourner discrètement un enregistrement (ce que j'ai fait ci-dessous).

Essayez en ligne 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