왼쪽 만 첫 번째 행


138

왼쪽 조인의 첫 번째 행만 얻는 것에 대한 많은 스레드를 읽었지만 어떤 이유로 든 작동하지 않습니다.

여기 내 구조가 있습니다 (물론 단순화 됨)

피드

id |  title | content
----------------------
1  | Feed 1 | ...

예술가

artist_id | artist_name
-----------------------
1         | Artist 1
2         | Artist 2

feeds_artists

rel_id | artist_id | feed_id
----------------------------
1      |     1     |    1 
2      |     2     |    1 
...

이제 기사를 가져 와서 첫 번째 아티스트 만 참여하고 싶습니다.

SELECT *
    FROM feeds 
    LEFT JOIN feeds_artists ON wp_feeds.id = (
        SELECT feeds_artists.feed_id FROM feeds_artists
        WHERE feeds_artists.feed_id = feeds.id 
    LIMIT 1
    )
WHERE feeds.id = '13815'

feeds_artists의 첫 번째 행만 가져 오지만 이미 작동하지 않습니다.

TOP데이터베이스로 인해 사용할 수 없으며 feeds_artists.artist_id날짜별로 결과를 정렬해야하므로 결과를 그룹화 할 수 없습니다 (이 방법으로 그룹화하여 결과를 얻었지만 최신이 아닌 결과)

OUTER APPLY로 무언가를 시도했지만 성공하지 못했습니다. 솔직히 말해서 나는 실제로 그 행에서 무슨 일이 일어나고 있는지 상상할 수 없습니다. 아마도 이것이 이것을 작동시키지 못하는 가장 큰 이유입니다.

해결책:

SELECT *
FROM feeds f
LEFT JOIN artists a ON a.artist_id = (
    SELECT artist_id
    FROM feeds_artists fa 
    WHERE fa.feed_id = f.id
    LIMIT 1
)
WHERE f.id = '13815'


솔루션은 다음과 같습니다 stackoverflow.com/a/7588442/612987
Wasim A.

솔루션을 답변으로 작성하여 투표에 참여하고 향후 방문자가 더 잘 볼 수 있도록해야합니다
fguillen

나는 당신이 옳다고 생각합니다-나는 또한 그것을 대답으로 추가했습니다.
KddC

답변:


97

아티스트 ID가 시간이 지남에 따라 증가한다고 가정 할 수 있다면 MIN(artist_id) 하면 가장 빠른 됩니다.

따라서 이와 같은 것을 시도하십시오 (평가되지 않은 ...)

SELECT *
  FROM feeds f
  LEFT JOIN artists a ON a.artist_id = (
    SELECT
      MIN(fa.artist_id) a_id
    FROM feeds_artists fa 
    WHERE fa.feed_id = f.feed_id
  ) a

빠른 답변 감사합니다. 이것은 정확한 대답은 아니지만 완전히 올바른 길로 안내했습니다. 나는 항상 하나를 다른 하나에서 의존하게 만드는 대신에 같은 수준에서 둘 다 참여하려고했습니다. 올바른 길로 인도 해 주셔서 대단히 감사합니다. 첫 게시물 수정
KddC

4
이 시점에서 간단한 하위 쿼리가 더 좋지 않습니까? 이제 조인과 하위 쿼리가 있습니다. 그냥 같은 문제에 대한 해결책을 찾고 있습니다 원인 :)
galdikas

2
하위 쿼리가 너무 느립니다.
Sinux

1
@Sinux는 "너무 느리게"정의합니다. 레코드 수와 주어진 요구 사항에 따라 다릅니다.
관찰자

1
이 작동하지 않습니다! 하위 쿼리는 부모 쿼리에서 필드를 전달하는 것을 허용하지 않습니다 !!!
Thư Sinh

53

부속 선택이없는 버전 :

   SELECT f.title,
          f.content,
          MIN(a.artist_name) artist_name
     FROM feeds f
LEFT JOIN feeds_artists fa ON fa.feed_id = f.id
LEFT JOIN artists a ON fa.artist_id = a.artist_id
 GROUP BY f.id

2
나는 이것이 첫 번째 행 (첫 번째 id 또는 다른 것 중 첫 번째 행)이라고 생각하지 않으며, 왼쪽 조인 행 중 하나를 임의로 선택합니다.
Sinux

26
이 쿼리는 잘못되었습니다. 세트의 첫 번째 아티스트 이름이 아닌 "가장 낮은"아티스트 이름을 선택합니다.
Glapa

5
질문이 잘못되었습니다 ...하지만 정확히 내가 원하는 것. 내 경우에는, 난 그냥에 합류하고있어 테이블에서 첫 번째 ID를 원한다.
드류 스티븐스

2
여기서 문제는 COUNT 또는 SUM을 수행하기로 결정한 경우 데이터를 망친 것입니다. Subselect의 문제점은 임시 테이블을 만들 때 데이터를 가져 오는 것이 무겁다는 것입니다. MySql이 LEFT JOIN 수준에서 LIMIT을 가질 수 있기를 바랍니다.
Shadoweb 2019

이 솔루션에는 성능 문제가 있습니다. 대신 최소 / 최대 솔루션을 사용하십시오.
Sadegh PM

25

@Matt Dodges는 저를 올바른 길로 안내합니다. 모든 답변에 다시 한 번 감사드립니다. 그 동안 많은 사람들이 도움이되었습니다. 다음과 같이 작동합니다.

SELECT *
FROM feeds f
LEFT JOIN artists a ON a.artist_id = (
    SELECT artist_id
    FROM feeds_artists fa 
    WHERE fa.feed_id = f.id
    LIMIT 1
)
WHERE f.id = '13815'

이것은 첫 번째 행에서만 작동하는 답변입니다. f.id조건 이 없으면 끊어 집니다.
Tajni

2

나는 다른 것을 사용했고 (더 나은 생각 ...) 공유하고 싶습니다.

"group"절이있는 VIEW를 만들었습니다.

CREATE VIEW vCountries AS SELECT * PROVINCES GROUP BY country_code

SELECT * FROM client INNER JOIN vCountries on client_province = province_id

나는 아직 우리가 분석에 잘못 되었기 때문에이 솔루션을 수행해야한다고 생각합니다. 적어도 제 경우에는 ...하지만 때로는 모든 것을 다시 디자인하기 위해이 작업을 수행하는 것이 더 저렴합니다 ...

도움이 되길 바랍니다!


각각에 대해 여러 행 (지방?)이 가정이다 country_code, GROUP BY부적절가. 참조하십시오 ONLY_FULL_GROUP_BY.
Rick James

LEFT / INNER JOIN 전용으로보기를 만들 필요는 없습니까?! 하위 쿼리 나 WITH x AS (절을 사용할 수 있습니까 ?
kiradotee

2

여기에 몇 가지 대답을 바탕으로, 나는 나를 위해 일한 것을 발견했고 무슨 일이 일어나고 있는지 일반화하고 설명하고 싶었습니다.

변하게 하다:

LEFT JOIN table2 t2 ON (t2.thing = t1.thing)

에:

LEFT JOIN table2 t2 ON (t2.p_key = (SELECT MIN(t2_.p_key) 
    FROM table2 t2_ WHERE (t2_.thing = t1.thing) LIMIT 1))

t1과 t2를 연결하는 조건 ON은 내부 쿼리와 내부 쿼리로 이동 합니다 WHERE. MIN(primary key)또는LIMIT 1 차종에만 1 행은 내부 쿼리에서 반환되어 있는지 확인하십시오.

하나의 특정 행을 선택한 후 ON어떤 행 인지 알려야합니다 . 그 이유는ON 조인 된 테이블의 기본 키를 비교하는 입니다.

내부 쿼리 (예 : order + limit)로 재생할 수 있지만 원하는 행의 기본 키 하나를 반환 ON하여 정확한 행을 조인해야합니다.


참고 : 또한에만 작동 LIMIT합니다 MIN. ON성능 영향을 피 하려면 조건이 결합 된 테이블 기본 키에 있어야합니다.
oriadam

1

보다 일반적인 답변 을 드리고 싶습니다 . LEFT JOIN의 첫 번째 항목 만 선택하려는 경우 를 처리 합니다 .

GROUP_CONCATS 하위 쿼리를 사용하여 원하는대로 정렬 한 다음 GROUP_CONCAT의 결과를 분할하고 첫 번째 항목 만 가져갈 수 있습니다.

LEFT JOIN Person ON Person.id = (
    SELECT SUBSTRING_INDEX(
        GROUP_CONCAT(FirstName ORDER BY FirstName DESC SEPARATOR "_" ), '_', 1)
    ) FROM Person
);

ORDER BY 옵션 으로 DESC 가 있으므로 "Zack"과 같은 사람의 개인 ID를 반환합니다. "Andy"와 같은 이름을 가진 사람을 원하면 ORDER BY FirstName DESCORDER BY FirstName ASC로 변경합니다. 합니다.

이것은 주문의 힘을 당신의 손 안에 맡기므로 민첩합니다. 그러나 많은 테스트를 거친 후에 는 확장 성이 떨어집니다. 사용자와 많은 데이터가있는 상황에서는 .

그러나 관리자를 위해 데이터 집약적 보고서를 실행하는 데 유용합니다.


GROUP_CONCAT값의 개수가 제한되어 긴만큼 트릭이 좋다. 기본 제한은 1024 자입니다.
Rick James
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.