175

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

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

フィード

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、日付で並べ替える必要があるため、結果をグループ化できません(この方法でグループ化して結果を取得しましたが、結果は最新ではありません)

OUTERAPPLYでも何かを試しましたが成功しませんでした。正直なところ、私はそれらの行で何が起こっているのか本当に想像できません-おそらくこれを機能させることができない最大の理由です。

解決:

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

8 に答える 8

120

アーティスト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
于 2013-03-25T23:10:07.093 に答える
57

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

   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
于 2013-12-12T11:47:24.850 に答える
41

@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'
于 2019-01-17T09:59:54.453 に答える
7

ここでのいくつかの回答に基づいて、私は自分に役立つものを見つけ、何が起こっているのかを一般化して説明したいと思いました。

変換:

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内部クエリに移動されますWHEREMIN(primary key)またはは、LIMIT 1内部クエリによって1行のみが返されることを確認します。

特定の行を1つ選択した後、ONそれがどの行であるかを通知する必要があります。そのため、ONは結合されたテーブルの主キーを比較しています。

内部クエリ(つまり、order + limit)で遊ぶことができますが、ON結合する正確な行を指示する目的の行の1つの主キーを返す必要があります。

アップデート-MySQL5.7以降の場合

MySQL 5.7+に関連する別のオプションは、ANY_VALUE+を使用することGROUP BYです。必ずしも最初のアーティスト名ではないアーティスト名が選択されます。

SELECT feeds.*,ANY_VALUE(feeds_artists.name) artist_name
    FROM feeds 
    LEFT JOIN feeds_artists ON feeds.id = feeds_artists.feed_id 
GROUP BY feeds.id

ANY_VALUEの詳細:https ://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

于 2020-04-30T11:24:38.997 に答える
2

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

「group」句を持つVIEWを作成しました

CREATE VIEW vCountries AS SELECT * PROVINCES GROUP BY country_code

SELECT * FROM client INNER JOIN vCountries on client_province = province_id

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

お役に立てば幸いです。

于 2018-03-09T14:11:45.437 に答える
1

もっと一般的な答えを出したいです。LEFTJOINの最初のアイテムのみを選択したい場合に対応するもの。

必要なものを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 BYFirstNameDESCをORDERBYFirstNameASCに変更します。

これは、注文の力を完全にあなたの手の中に置くので、機敏です。ただし、多くのテストを行った後、ユーザーとデータが多い状況では拡張性が低くなります。

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

于 2018-09-17T20:06:11.570 に答える
0

これがgroupby句を使用した私の答えです。

SELECT *
FROM feeds f
LEFT JOIN 
(
    SELECT artist_id, feed_id
    FROM feeds_artists
    GROUP BY artist_id, feed_id 
) fa ON fa.feed_id = f.id
LEFT JOIN artists a ON a.artist_id = fa.artist_id
于 2020-11-24T10:52:51.183 に答える
0

DB2やPostgreSQLなどの一部のデータベースでは、 :LATERALでサブクエリを指定するためにキーワードを使用する必要があります(ここでは、DB2用です)。LEFT JOIN

SELECT f.*, a.*
FROM feeds f
LEFT JOIN LATERAL  
(
    SELECT artist_id, feed_id
    FROM feeds_artists sfa
    WHERE sfa.feed_id = f.id
    fetch first 1 rows only
) fa ON fa.feed_id = f.id
LEFT JOIN artists a ON a.artist_id = fa.artist_id
于 2020-11-25T17:11:55.650 に答える