FIND_IN_SET() と IN(): クエリ結果の矛盾を理解する
リレーショナル データベースをクエリするときは、その違いを理解する必要がありますFIND_IN_SET() 関数と IN() 関数の間。この記事では、特定のデータベース シナリオにおけるそれらの動作を検証します。
問題:
orders と company という 2 つのテーブルについて考えます。 order テーブルには、会社 ID のカンマ区切りリストを保持する AttachedCompanyIDs 列が含まれています。会社テーブルには実際の会社名が含まれています。 FIND_IN_SET() 関数を使用して注文に関連付けられた会社名を取得するクエリを実行すると、期待されるすべての結果が返されます。ただし、クエリ内で FIND_IN_SET() を IN() に置き換えると、最初の会社名のみが返されます。
原因:
IN() 関数は、attachedCompanyID を単一のものとして解釈します。整数ですが、FIND_IN_SET() はそれを文字列として扱います。 AttachedCompanyIDs が整数としてキャストされる場合、最初の数字以外の文字 (カンマ) までの数字のみが保持されます。したがって、IN() クエリは、カンマ区切りリストの最初の番号に関連付けられた会社のみを返します。
解決策:
この問題を回避するために、PostgreSQL は次のことを提供します。より堅牢なソリューション:
SELECT name FROM orders JOIN company ON companyID = ANY(('{' || attachedCompanyIDs || '}')::INT[]) WHERE orderID = 1;
このクエリは、ANY() 関数を利用してキャストします。 AttachedCompanyIDs を配列として使用し、companyID のインデックスを効果的に使用できるようにします。
Update:
配列のサポートがない MySQL データベースの場合は、別のアプローチを使用できます。 :
SELECT name FROM orders CROSS JOIN ( SELECT 1 AS pos UNION ALL SELECT 2 AS pos UNION ALL SELECT 3 AS pos UNION ALL SELECT 4 AS pos UNION ALL SELECT 5 AS pos ) q JOIN company ON companyID = CAST(NULLIF(SUBSTRING_INDEX(attachedCompanyIDs, ',', -pos), SUBSTRING_INDEX(attachedCompanyIDs, ',', 1 - pos)) AS UNSIGNED);
このクエリは、潜在的な位置を反復して、attachedCompanyID から一致する部分文字列を抽出します。会社ID。これには複数の結合が含まれますが、カンマ区切りリスト内の会社 ID の数が限られているシナリオでも引き続き機能します。
以上がFIND_IN_SET() と IN(): 1 つはすべての結果を返し、もう 1 つは最初の結果のみを返すのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。