Je n'ai aucune idée du titre de cette question, je suis donc désolé si vous avez été induit en erreur par le titre. De plus, je suis désolé pour les noms de tables / colonnes en allemand, n'hésitez pas à demander si vous ne comprenez rien.

Je vais d'abord expliquer la partie pertinente de ma base de données:

Je dois essentiellement des tables: Termine (rendez-vous) et Buchungen (réservations). Un Termin peut avoir plusieurs Buchungen et un Buchung peut avoir plusieurs Termine (il s'agit donc d'une connexion n à n) . Ils sont connectés à la table TermineBuchungen.

Le tableau Termine a les colonnes Id et Datum (Date), le tableau Buchungen a Id et Bemerkung (Annotation) et le tableau TermineBuchungen (évidemment) a Termin et Buchung.

Pour avoir toutes les informations pertinentes sur un Buchung , j'ai besoin de l ' Id et du Bemerkung de celui-ci ainsi que de l' Termin Id et Datum du Termin concernant le Buchung qui a le Datum le plus élevé - c'est-à-dire le plus récent Résiliation concernant ce Buchung .

Ce que je veux maintenant, ce sont tous les Buchungen (c'est-à-dire toutes les informations pertinentes sur les Buchungen comme expliqué ci-dessus) qui sont connectés à un Termin spécifique. Cependant, ce Termin ne doit pas nécessairement être le Termin le plus récent des Buchungen - cela signifie que le Termin <(maximum) renvoyé / em> du Buchungen peut être un autre, que celui que j'ai recherché initialement.

Permettez-moi de vous expliquer cela à l'aide d'un exemple:

Termine:
Id    Datum
0     1/1/2000
1     1/1/2001
2     1/1/2002

Buchungen:
Id    Bemerkung
0     'a'
1     'b'
2     'c'

TermineBuchungne:
Termin    Buchung
0         0
0         1
1         1
2         1

Maintenant, je veux toutes les informations pertinentes sur Buchung pour tous les Buchungen concernant Termin 0. Le résultat devrait ressembler à ceci:

Id    Bemerkung    NewestTermninId    NewestTerminDatum
0     'a'          0                  1/1/2000
1     'b'          1                  1/1/2001

Le deuxième exemple est particulièrement intéressant, car le plus récent Termin ici n'est pas le Termin 0.

J'ai essayé de réaliser ceci comme ça:

SELECT
  b.Id,
  b.Bemerkung,
  t.Id AS TerminId,
  t.Datum AS TerminDatum
FROM Buchungen AS b
  INNER JOIN TermineBuchungen AS tb ON b.Id = tb.Buchung
  LEFT JOIN
  (
    SELECT t2.Id, t2.Datum
    FROM Termine AS t2
      INNER JOIN TermineBuchungen AS tb2 ON t2.Id = tb2.Termin AND tb2.Buchung = b.Id
    WHERE t2.Datum =
          (
            SELECT MAX(t3.Datum)
            FROM Termine AS t3
              INNER JOIN TermineBuchungen AS tb3 ON t3.Id = tb3.Termin AND tb3.Buchung = b.Id
          )
  ) AS t ON 1 = 1
WHERE tb.Termin = 1

Mais j'obtiens l'erreur L'identifiant en plusieurs parties "b.Id" est introuvable.

J'utilise un serveur MS SQL.

J'ai essayé de trouver une réponse à cette question pendant quelques heures maintenant, mais comme mentionné, je ne sais pas trop comment intituler ce problème.

0
MetaColon 27 nov. 2017 à 19:36

3 réponses

Meilleure réponse

Vous devriez pouvoir résoudre votre problème en utilisant APPLIQUER EXTERIEUR. OUTER et CROSS APPLY sont utilisés lorsque vous devez interroger des sous-requêtes corrélées, exactement comme dans votre cas:

SELECT
  b.Id,
  b.Bemerkung,
  t.Id AS TerminId,
  t.Datum AS TerminDatum
FROM Buchungen AS b
  INNER JOIN TermineBuchungen AS tb ON b.Id = tb.Buchung
  OUTER APPLY
  (
    SELECT t2.Id, t2.Datum
    FROM Termine AS t2
      INNER JOIN TermineBuchungen AS tb2 ON t2.Id = tb2.Termin AND tb2.Buchung = b.Id
    WHERE t2.Datum =
          (
            SELECT MAX(t3.Datum)
            FROM Termine AS t3
              INNER JOIN TermineBuchungen AS tb3 ON t3.Id = tb3.Termin AND tb3.Buchung = b.Id
          )
  ) AS t ON 1 = 1
WHERE tb.Termin = 1

Dans le fil de discussion que j'ai attaché à cette réponse, vous pouvez voir que votre cas est 3) Réutiliser un alias de colonne.

1
rigerta 27 nov. 2017 à 16:44

Requête plus simple, y compris des exemples de données:

-- sample data

;with Termine as (
    select * from (values 
        (0, '2000-1-1'),
        (1, '2001-1-1'),
        (2, '2002-1-1')
    ) t(Id, Datum)
),
Buchungen as (
    select * from (values 
        (0, 'a'),
        (1, 'b'),
        (2, 'c')
    ) t(Id, Bemerkung)
),
TermineBuchungen as (
    select * from (values 
        (0, 0),
        (0, 1),
        (1, 1),
        (2, 1)
    ) t(Termin, Buchung)
)

-- solution

select
    Id,
    Bemerkung,
    TerminId,
    TerminDatum
from (
    select b.Id, b.Bemerkung, TerminId = t.Id, TerminDatum = t.Datum, MaxTerminDatum = max(t.Datum) over(partition by b.Id) from Buchungen b
    join TermineBuchungen tb ON b.Id = tb.Buchung
    join Termine t on t.Id = tb.Termin
) t
where TerminDatum = MaxTerminDatum

Il renvoie TerminId = 2 contrairement à votre exemple de résultat car TerminId = 2 est en effet lié à Buchung = 1 et il a la date la plus élevée.

1
Alexey 27 nov. 2017 à 17:08

Voici une autre solution:

SELECT
  b.Id,
  b.Bemerkung,
  t.Id AS TerminId,
  t.Datum AS TerminDatum
FROM Buchungen AS b
  INNER JOIN TermineBuchungne AS tb ON b.Id = tb.Buchung
  LEFT JOIN
  (
    SELECT t2.Id, t2.Datum, tb2.Buchung
    FROM Termine AS t2
      INNER JOIN TermineBuchungne AS tb2 ON t2.Id = tb2.Termin  
    WHERE t2.Datum =
          (
            SELECT MAX(t3.Datum) 
            FROM Termine AS t3
              INNER JOIN TermineBuchungne AS tb3 ON t3.Id = tb3.Termin 
              INNER JOIN Buchungen b ON tb3.Buchung = b.Id
          )
  ) AS t ON t.Buchung = b.Id
WHERE tb.Termin = 1
-1
Ms workaholic 27 nov. 2017 à 17:02
47515708