Top 1 với sự tham gia bên trái


92

Với truy vấn bên dưới có thể có nhiều hàng trong dps_markers có cùng một khóa đánh dấu nhưng chúng tôi chỉ muốn kết hợp với hàng đầu tiên. Nếu tôi thực hiện truy vấn này và loại bỏ top 1 và ĐẶT HÀNG BẰNG CÁCH, tôi nhận được một giá trị cho mbg.marker_value nhưng chạy như vậy nó luôn trả về null

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'

Câu trả lời:


196

Sử dụng ÁP DỤNG NGOÀI TRỜI thay vì THAM GIA TRÁI:

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';

Không giống như THAM GIA, ÁP DỤNG cho phép bạn tham chiếu u.id bên trong truy vấn bên trong.


Cảm ơn @Remus, Nó đã giúp tôi.
Sarthak Shah

2

Chìa khóa để gỡ lỗi các tình huống như thế này là tự chạy truy vấn con / chế độ xem nội tuyến để xem đầu ra là gì:

  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

Chạy điều đó, bạn sẽ thấy rằng profile_idgiá trị không khớp với u.idgiá trị của u162231993, điều này sẽ giải thích lý do tại sao bất kỳ mbgtham chiếu nào sẽ trả về null(nhờ phép nối bên trái; bạn sẽ không nhận được gì nếu đó là phép nối bên trong).

Bạn đã tự mã hóa mình vào một góc bằng cách sử dụng TOP, bởi vì bây giờ bạn phải điều chỉnh truy vấn nếu bạn muốn chạy nó cho người dùng khác. Một cách tiếp cận tốt hơn sẽ là:

   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'

Cùng với đó, bạn có thể thay đổi idgiá trị trong wheremệnh đề để kiểm tra bản ghi cho bất kỳ người dùng nào trong hệ thống.


1

Bởi vì TOP 1từ truy vấn phụ có thứ tự không có profile_id = 'u162231993' Xóa where u.id = 'u162231993'và xem kết quả khi đó.

Chạy truy vấn phụ riêng để hiểu điều gì đang xảy ra.


được rồi tôi nghĩ bây giờ tôi hiểu ý bạn rồi. vẫn cần có thể làm cho điều này hoạt động. Về cơ bản, bảng dps_markers của bảng có thể có nhiều hơn một hàng gây ra lỗi trong truy vấn bên ngoài mà chúng ta cần ngăn chặn.
dstarh

0

Damir đúng,

Truy vấn con của bạn cần đảm bảo rằng dps_user.id bằng um.profile_id, nếu không nó sẽ lấy hàng trên cùng có thể, nhưng có thể không bằng id của bạn là 'u162231993'

Truy vấn của bạn sẽ giống như sau:

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'

vâng, tôi vừa thử điều đó nhưng u.id không hiển thị trong phần chọn phụ Không thể liên kết số nhận dạng nhiều phần "u.id".
dstarh

Bạn có thể đưa WHERE um.profile_id = 'u162231993'vào truy vấn phụ và WHERE mbg.marker_value IS NOT NULLở bên ngoài.
Damir Sudarevic

tôi sẽ không biết profile_id, nó sẽ đến từ một tham gia khác. Điều này đã được rút ra từ một truy vấn lớn hơn nhiều
dstarh

tốt, hãy sử dụng biến @SearchFor = 'u162231993'và sau đó sử dụng biến đó trong WHEREhoặc đăng một số dữ liệu và cấu trúc bảng để người khác có thể trợ giúp và dùng thử.
Damir Sudarevic
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.