次の SQL リクエストに対する解決策を何日も探し続けましたが、成功しませんでした。
私の状況:
テーブルが 3 つあります (リンク: https://i.stack.imgur.com/BswG0.png)
企業 (企業を含む)
リクエスト: 企業から送信されたリクエストが含まれます
オファー: 企業から送信されたリクエストに対するオファーだけでなく、企業に直接送信された自発的なオファーも含まれます。
テーブル Offers には 2 つの外部キーが含まれています:
オファー_fk_companies
オファー_fk_requests
オファーが企業から送信されたリクエストにリンクされている場合、フィールド Offers_fk_requests には値が含まれ、フィールド Offers_fk_companies は null になります。
オファーがリクエストなしで企業に直接送信される場合、フィールド Offers_fk_requests は null で、フィールドはオフになりますrs_fk_companies には値が含まれています。
オファー テーブルに対して SELECT を実行して、(リクエストなしで)企業に直接送信されたオファーのすべてのエントリを取得したいと思います。また、企業からのリクエスト後に送信されたオファーのエントリも取得したいと考えています。
私はこのリクエストを持ってきました:
SELECT *
FROM `offers`
LEFT JOIN `requests` ON `offers_fk_requests` = requests.`id`
JOIN `companies` AS companies1 ON requests.`fk_companies` = companies1.`companies_id`
LEFT JOIN `companies` AS companies2 ON offers.`fk_companies` = companies2.`companies_id`
WHERE ...
上記のリクエストを実行した場合と、2 つの異なるリクエストに分けた場合では異なる結果が得られます。
SELECT *
FROM `offers`
LEFT JOIN `requests` ON `offers_fk_requests` = requests.`id`
JOIN `companies` AS companies1 ON requests.`fk_companies` = companies1.`companies_id`
WHERE ...
SELECT *
FROM `offers`
LEFT JOIN `companies` AS companies2 ON offers.`fk_companies` = companies2.`companies_id`
WHERE ...
基本的に、2 つの異なるパスがあります。1 つはテーブル オファーからテーブル会社に行くパス、もう 1 つはテーブル オファーからテーブル会社に行くが、中間のテーブル リクエストを経由するパスです。
これらの個別のリクエストを組み合わせた場合と同じ結果を、単一のリクエストで達成するにはどうすればよいですか?
フィールドの数が異なるため、UNION は使用できません。しらないうーん、他に解決策はどこにあるでしょうか...
よろしくお願いします。
編集
元のリクエストに従い、すべての結合に LEFT OUTER JOIN を使用すると、機能するようです。
選択 *
オファーから
LEFT OUTER JOIN リクエスト ON Offers_fk_requests =requests.id
LEFT OUTER 企業を企業 1 として結合します request.fk_companies = Companies1.companies_id
LEFT OUTER JOIN Companies AS Companies2 ON Offers.fk_companies = Companies2.companies_id
どこ ...
@Marcel: 正しい方向に導いていただき、ありがとうございます!
こんにちは、ようこそe スタックオーバーフロー上。これはよく準備された完全な質問です!
– マルセル
2020 年 9 月 3 日 10:44
オファーに興味があると言うとき、そもそもなぜ参加したいのですか?オファーを選択し、含まれている外部キーのみに基づいてフィルタリングを実行できます。
– マルセル
2020 年 9 月 3 日 10:45
@マルセル。コメントありがとうございます。一致するすべてのエントリを 1 つの SQL リクエストで取得する必要があります。これは、日付に従ってエントリを並べ替える必要があることと、アプリケーション内でエントリを個別に表示することが意味がないためです。エントリは混合する必要があります。
– ジャン・ネマール
2020 年 9 月 3 日 10:47
------------------------
すべてを一度に行う必要があるという OP のコメントに基づいて、単純に実行することをお勧めします
SELECT *
FROM offers
LEFT OUTER JOIN companies ON companyId /*simplified*/
LEFT OUTER JOIN requests ON requestId /*simplified*/
左外部結合は、一致する場合にのみデータを結合し、一致しない場合はフィールドを空のままにします。したがって、利用可能な Fi が得られ、すべてのオファーが得られることになります。フィールドは埋められています。
ただし、現在の設計では、リクエストがあるものについては、会社データが空になります。リクエストに基づくものにも会社の外部キーを設定し、このキーを必須にすることをお勧めします。いずれにせよ、リクエストのせいで、彼らは会社と結びついています。
3
あなたの提案をテストしたところです。それは機能しますが、すべてのオファーについて、不要な情報を含む膨大な結果セットが得られます。したがって、あなたの解決策は残念ながら私の状況には適切ではありません。
&ndアッシュ ジャン・ネマール
2020 年 9 月 3 日、11:20
リクエスト内で何らかの条件を使用して、次のような最終リクエストを作成することは可能でしょうか: IF fieldA is null then do request1 ELSE do request2?リクエストで条件を使用したことがないので、すべてが初めてで、それが可能かどうかさえわかりません。
– ジャン・ネマール
2020 年 9 月 3 日 11:29
2 つの異なるリクエストが必要な場合でも問題ありません。ただし、どちらを行うかはデータベースではなくアプリケーションで決定する必要があります。
– マルセル
2020 年 9 月 3 日 14:23
------------------------
UNION を使用する場合、欠落しているフィールドには NULL を入力できます。
SELECT *
FROM `offers`
LEFT JOIN `requests` ON `offers_fk_requests` = requests.`id`
JOIN `companies` AS companies1 ON requests.`fk_companies` = companies1.`companies_id`
UNION ALL SELECT null, null, null, `fk_companies`, `companies_id`
FROM `offers`
LEFT JOIN `companies` AS companies2 ON offers.`fk_companies` = companies2.`companies_id`
WHERE `companies_id` IS NOT NULL;
同じ列内のすべての Companies_id を取得するには、次のクエリを使用できます。
SELECT `requests`.`id` AS `requests_id`, coalesce(`requests`.`fk_companies`, `companies`.`companies_id`) AS `companies_id`
FROM `offers`
LEFT JOIN `companies` ON `offers`.`fk_companies` = `companies`.`companies_id`
LEFT JOIN `requests` ON `offers`.`offers_fk_requests` = `requests`.`id`;
db フィドルを参照してください。
0