1. ホーム
  2. mysql

[解決済み] FIND_IN_SET()とIN()の比較

2022-06-25 02:28:01

質問

私のデータベースには2つのテーブルがあります。 1つは注文のためであり、1つは会社のためです。

受注はこのような構造になっています。

OrderID     |     attachedCompanyIDs
------------------------------------
   1                     1,2,3
   2                     2,4

そしてCompanyはこのような構造になっています。

CompanyID      |        name
--------------------------------------
    1                 Company 1
    2                 Another Company
    3                 StackOverflow
    4                 Nothing

注文の会社名を取得するには、次のようなクエリを実行すればよいですね。

SELECT name FROM orders,company
WHERE orderID = 1 AND FIND_IN_SET(companyID, attachedCompanyIDs)

このクエリは問題なく動作しますが、次のクエリは動作しません。

SELECT name FROM orders,company
WHERE orderID = 1 AND companyID IN (attachedCompanyIDs)

なぜ最初のクエリは動作し、2番目のクエリは動作しないのでしょうか?

最初のクエリは返されます。

name
---------------
Company 1
Another Company
StackOverflow

2つ目のクエリは返すだけです。

name
---------------
Company 1

これはなぜかというと、最初のクエリではすべての会社が返されるのに、2番目のクエリでは最初の会社だけが返されるからです。

どのように解決するのですか?

SELECT  name
FROM    orders,company
WHERE   orderID = 1
        AND companyID IN (attachedCompanyIDs)

attachedCompanyIDs はスカラー値で、これを INT にキャストされるスカラー値です (型は companyID ).

キャストは最初の数字でないもの(あなたの場合はカンマ)までの数字しか返しません。

このように

companyID IN ('1,2,3') ≡ companyID IN (CAST('1,2,3' AS INT)) ≡ companyID IN (1)

PostgreSQL では、文字列を配列にキャストすることができます(あるいは、そもそも配列として格納することもできます)。

SELECT  name
FROM    orders
JOIN    company
ON      companyID = ANY (('{' | attachedCompanyIDs | '}')::INT[])
WHERE   orderID = 1

で、これはさらに companyID .

残念ながら、これは MySQL は配列をサポートしていないため、これは動作しません。

この記事は面白いかもしれません( #2 ):

更新しました。

カンマ区切りリストの値の数に何らかの妥当な制限がある場合 (たとえば 5 を超えない)ので、このクエリを使用してみることができます。

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)