Programing

조인 된 테이블에서 LIMIT 1로 MySQL JOIN

crosscheck 2020. 12. 25. 23:00
반응형

조인 된 테이블에서 LIMIT 1로 MySQL JOIN


두 테이블을 조인하고 싶지만 table1의 레코드 당 table2의 레코드 1 개만 가져옵니다.

예를 들면 :

SELECT c.id, c.title, p.id AS product_id, p.title
FROM categories AS c
JOIN products AS p ON c.id = p.category_id

이것은 products내가 원하는 것이 아닌 모든 레코드를 가져옵니다 . 카테고리 당 1 개의 [첫 번째] 제품을 원합니다 ( sort제품 필드에 열이 있습니다).

어떻게해야합니까?


나는 다음과 같은 것을 시도 할 것입니다.

SELECT C.*,
      (SELECT P.id, P.title 
       FROM products as P
       WHERE P.category_id = C.id
       LIMIT 1)
FROM categories C

비슷한 질문에 설명 된 다른 접근 방식이 더 마음에 듭니다 : https://stackoverflow.com/a/11885521/2215679

이 방법은 특히 SELECT에 둘 이상의 필드를 표시해야하는 경우에 더 좋습니다. Error Code: 1241. Operand should contain 1 column(s)각 열 을 피 하거나 두 번 하위 선택합니다.

상황에 따라 쿼리는 다음과 같아야합니다.

SELECT
 c.id,
 c.title,
 p.id AS product_id,
 p.title AS product_title
FROM categories AS c
JOIN products AS p ON
 p.id = (                                 --- the PRIMARY KEY
  SELECT p1.id FROM products AS p1
  WHERE c.id=p1.category_id
  ORDER BY p1.id LIMIT 1
 )

@ goggin13이 수락 한 답변이 잘못된 것 같습니다. 현재까지 제공된 다른 솔루션은 작동하지만 n + 1 문제로 인해 성능 저하가 발생합니다.

n + 1 문제 : 만약 100 개의 카테고리가 있다면, 우리는 카테고리를 얻기 위해 1 개의 선택을해야 할 것이고, 반환 된 100 개의 카테고리 각각에 대해, 우리는 그 카테고리의 제품을 얻기 위해 선택을해야 할 것입니다. 따라서 101 개의 SELECT 쿼리가 수행됩니다.

내 대체 솔루션은 n + 1 문제를 해결하므로 2 개의 선택 만 수행되므로 결과적으로 훨씬 더 성능이 향상됩니다.

SELECT
  *
FROM
    (SELECT c.id, c.title, p.id AS product_id, p.title
    FROM categories AS c
    JOIN products AS p ON c.id = p.category_id
    ORDER BY c.id ASC) AS a 
GROUP BY id;

SELECT c.id, c.title, p.id AS product_id, p.title
FROM categories AS c
JOIN products AS p ON c.id = p.category_id
GROUP BY c.id

제품의 첫 번째 데이터를 반환합니다 (제한 1과 같음).


이건 어때?

SELECT c.id, c.title, (SELECT id from products AS p 
                            WHERE c.id = p.category_id 
                            ORDER BY ... 
                            LIMIT 1)
   FROM categories AS c;

With 절이 트릭을 수행합니다. 이 같은:

WITH SELECTION AS (SELECT id FROM products LIMIT 1)
SELECT a.id, c.id, c.title FROM selection a JOIN categories c ON (c.id = a.id);

열에 MIN()imial 값이있는 제품을 원한다고 가정하면 sort다음과 같습니다.

SELECT 
  c.id, c.title, p.id AS product_id, p.title
FROM 
  categories AS c
INNER JOIN (
  SELECT
    p.id, p.category_id, p.title
  FROM
    products AS p
  CROSS JOIN (
    SELECT p.category_id, MIN(sort) AS sort
    FROM products
    GROUP BY category_id
  ) AS sq USING (category_id)
) AS p ON c.id = p.category_id

When using postgres you can use the DISTINCT ON syntex to limit the number of columns returned from either table.

Here is a sample of the code:

SELECT c.id, c.title, p.id AS product_id, p.title FROM categories AS c JOIN ( SELECT DISTINCT ON(p1.id) id, p1.title, p1.category_id FROM products p1 ) p ON (c.id = p.category_id)
The trick is not to join directly on the table with multiple occurrences of the id, rather, first create a table with only a single occurrence for each id


Replace the tables with yours:

SELECT * FROM works w 
LEFT JOIN 
(SELECT photoPath, photoUrl, videoUrl FROM workmedias LIMIT 1) AS wm ON wm.idWork = w.idWork

ReferenceURL : https://stackoverflow.com/questions/6879391/mysql-join-with-limit-1-on-joined-table

반응형