web-dev-qa-db-ja.com

LEFT JOINのみ最初の行

左結合の最初の行のみを取得することについて多くのスレッドを読みましたが、何らかの理由でこれはうまくいきません。

これが私の構造です(もちろん簡略化されています)

フィード

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'
120
KddC

@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'
10
KddC

アーティスト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
89
Matt Dodge

副選択なしのバージョン:

   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
51

私は何か他のものを使用しました(私はもっと良いと思います...)、それを共有したい:

「グループ」句を持つビューを作成しました

CREATE VIEW vCountries AS SELECT * PROVINCES GROUP BY country_code

SELECT * FROM client INNER JOIN vCountries on client_province = province_id

言いたいのは、WE DID分析で何かが間違っているからです...少なくとも私の場合は...しかし、これを行う方が安価な場合があるため、このソリューションを実行する必要があると思いますすべてを再設計するために...

私はそれが役立つことを願っています!

2
Ari Waisberg

もっと一般化された答えを出したい。 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
);

DESCORDER BYオプションとしてあるため、これは "Zack"のような人のPerson IDを返します。 「Andy」などの名前を持つ人が必要な場合は、ORDER BY FirstName DESCORDER BY FirstName ASCに変更します。

これは、注文の力を完全にあなたの手の中に置くため、機敏です。しかし、多くのテストを行った後、うまくスケーリングしませんたくさんのユーザーとたくさんのデータがある状況で。

ただし、管理者向けのデータ集約型レポートの実行には役立ちます。

1
HoldOffHunger