Sol birleştirme ile ilk 1


96

Aşağıdaki sorgu göz önüne alındığında, dps_markers'da aynı işaretleyici anahtarına sahip birden çok satır olabilir, ancak biz yalnızca ilkine karşı birleştirmek istiyoruz. Bu sorguyu alır ve ilk 1'i kaldırırsam ve ORDER BY mbg.marker_value için bir değer alırım ancak olduğu gibi çalıştırırsam her zaman boş döndürür

SELECT u.id, mbg.marker_value 
FROM dps_user u
LEFT JOIN 
    (SELECT TOP 1 m.marker_value, um.profile_id
     FROM dps_usr_markers um (NOLOCK)
         INNER JOIN dps_markers m (NOLOCK) 
             ON m.marker_id= um.marker_id AND 
                m.marker_key = 'moneyBackGuaranteeLength'
     ORDER BY m.creation_date
    ) MBG ON MBG.profile_id=u.id 
WHERE u.id = 'u162231993'

Yanıtlar:


204

LEFT JOIN yerine OUTER APPLY kullanın:

SELECT u.id, mbg.marker_value 
FROM dps_user u
OUTER APPLY 
    (SELECT TOP 1 m.marker_value, um.profile_id
     FROM dps_usr_markers um (NOLOCK)
         INNER JOIN dps_markers m (NOLOCK) 
             ON m.marker_id= um.marker_id AND 
                m.marker_key = 'moneyBackGuaranteeLength'
     WHERE um.profile_id=u.id 
     ORDER BY m.creation_date
    ) AS MBG
WHERE u.id = 'u162231993';

JOIN'den farklı olarak, UYGULA, iç sorgu içinde u.id'ye başvurmanıza izin verir.


Teşekkürler @ Remus, Bana yardımcı oldu.
Sarthak Shah

3

Bunun gibi durumlarda hata ayıklamanın anahtarı, çıktının ne olduğunu görmek için alt sorgu / satır içi görünümü kendi başına çalıştırmaktır:

  SELECT TOP 1 
         dm.marker_value, 
         dum.profile_id
    FROM DPS_USR_MARKERS dum (NOLOCK)
    JOIN DPS_MARKERS dm (NOLOCK) ON dm.marker_id= dum.marker_id 
                                AND dm.marker_key = 'moneyBackGuaranteeLength'
ORDER BY dm.creation_date

O Koşu, bunu görürdünüz profile_iddeğer eşleşmedi u.iddeğerini u162231993herhangi açıklıyor, mbgreferanslar dönecekti null(solda sayesinde katılmak; bir iç birleşim olsaydı şey elde etmem).

Kullanarak kendinizi bir köşeye kodladınız TOP, çünkü şimdi sorguyu diğer kullanıcılar için çalıştırmak istiyorsanız ince ayar yapmanız gerekiyor. Daha iyi bir yaklaşım şöyle olacaktır:

   SELECT u.id, 
          x.marker_value 
     FROM DPS_USER u
LEFT JOIN (SELECT dum.profile_id,
                  dm.marker_value,
                  dm.creation_date
             FROM DPS_USR_MARKERS dum (NOLOCK)
             JOIN DPS_MARKERS dm (NOLOCK) ON dm.marker_id= dum.marker_id 
                                         AND dm.marker_key = 'moneyBackGuaranteeLength'
           ) x ON x.profile_id = u.id
     JOIN (SELECT dum.profile_id,
                  MAX(dm.creation_date) 'max_create_date'
             FROM DPS_USR_MARKERS dum (NOLOCK)
             JOIN DPS_MARKERS dm (NOLOCK) ON dm.marker_id= dum.marker_id 
                                         AND dm.marker_key = 'moneyBackGuaranteeLength'
         GROUP BY dum.profile_id) y ON y.profile_id = x.profile_id
                                   AND y.max_create_date = x.creation_date
    WHERE u.id = 'u162231993'

Bununla , sistemdeki herhangi bir kullanıcının kayıtlarını kontrol etmek idiçin wherefıkradaki değeri değiştirebilirsiniz .


2

Çünkü TOP 1sıralı alt sorguda profile_id = 'u162231993' Kaldır where u.id = 'u162231993've sonuçları o zaman gör.

Neler olduğunu anlamak için alt sorguyu ayrı ayrı çalıştırın.


Tamam, sanırım şimdi ne demek istediğini anlıyorum. hala bunun işe yaraması gerekiyor. Temel olarak, dps_markers tablosunun birden fazla satırı olabilir ve bu da dış sorguda önlememiz gereken yinelemelere neden olur.
dstarh

1

Damir haklı,

Alt sorgunuz, dps_user.id değerinin um.profile_id değerine eşit olmasını sağlamalıdır, aksi takdirde "u162231993" kimliğinize eşit olabilecek, ancak muhtemelen eşit olmayan en üst satırı yakalar.

Sorgunuz şöyle görünmelidir:

SELECT u.id, mbg.marker_value 
FROM dps_user u
LEFT JOIN 
    (SELECT TOP 1 m.marker_value, um.profile_id
     FROM dps_usr_markers um (NOLOCK)
         INNER JOIN dps_markers m (NOLOCK) 
             ON m.marker_id= um.marker_id AND 
                m.marker_key = 'moneyBackGuaranteeLength'
     WHERE u.id = um.profile_id
     ORDER BY m.creation_date
    ) MBG ON MBG.profile_id=u.id 
WHERE u.id = 'u162231993'

1
evet bunu denedim ama u.id alt seçimde görünmüyor Çok parçalı tanımlayıcı "u.id" bağlanamadı.
dstarh

1
WHERE um.profile_id = 'u162231993'Alt sorguyu ve WHERE mbg.marker_value IS NOT NULLdışını girebilirsiniz .
Damir Sudarevic

1
profile_id bilgisini bilmeyeceğim, başka bir katılımdan olacak. Bu, çok daha büyük bir sorgudan
çıkarıldı

1
peki, değişkeni kullanın @SearchFor = 'u162231993've sonra onu kullanın WHEREveya bazı veriler ve tablo yapıları gönderin, böylece diğer insanlar yardımcı olabilir ve deneyebilir.
Damir Sudarevic
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.