web-dev-qa-db-ja.com

複数の列で複数の値を検索する

私はこのフィールドを持つテーブル結果を持っています:

  • id
  • results_id
  • number_one(int)
  • number_two(int)
  • number_three(int)
  • number_four(int)
  • number_five(int)

各number_ *列には、01から90までの数値を含めることができます。

90個のチェックボックスが付いた検索フォームがあります。ユーザーは最大5つのチェックボックスにチェックマークを付けることができます。

ユーザーがnチェックボックスを選択したら、それらすべての値を含む行を検索するクエリを作成する必要がありますが、5つの列のいずれかに数値を含めることができます。

例:

ユーザーがチェックボックス02、12、20にチェックマークを付けます。3つの数値すべてを含むすべての行を取得する必要がありますが、数値は任意のnumber_ *列に含めることができます。 20は列number_oneに、02は列number_threeに、12は列number_fourに配置できます。このクエリを作成するにはどうすればよいですか?

また、5列ではなく1列を使用する方が良いでしょうか?結果表:

  • id
  • result_id
  • 数値(文字列)

列番号には02-12-20-57-84が含まれます-ここで-はセパレータです。

例:ユーザーがチェックボックス02、12、および20をチェックしているため、クエリは

SELECT * 
FROM results 
WHERE numbers LIKE "%02%" 
    AND numbers LIKE "%12%" 
    AND numbers LIKE "%20%";
5
Tyler Durden

個人的に私はあなたのテーブルを作成します

  • id
  • result_id

ただし、値列に単一の値が含まれています。これで、値列にインデックスを付けることができるようになり、これにより処理速度が大幅に向上します。クエリは次のようになります。

SELECT result_id
FROM TableName
WHERE VALUE IN ('02','12','20')
GROUP BY result_id
HAVING COUNT(1) >= 3

これの利点の1つは、1つの一致、2つの一致などを簡単に確認できることです。また、確認できる項目の数を50に増やすことができ、テーブル構造を変更する必要がなくなります。

今言われていることはそれはあなたのために機能しません。今私はこのようなものを使うでしょう:

SELECT *
FROM TableName
WHERE '02' IN (Number_1, Number_2, Number_3, Number_4, Number_5)
  AND '12' IN (Number_1, Number_2, Number_3, Number_4, Number_5)
  AND '20' IN (Number_1, Number_2, Number_3, Number_4, Number_5)
6
Kenneth Fisher

これは、idが主キーであり、RDBMSでCTEを使用できることを前提としています。

これは、#Tempの値の数に関係なく機能します。

If(OBJECT_ID('tempdb..#Temp') Is Not Null)  Drop Table #Temp

CREATE TABLE #Temp
(
    selectedValue INT
)

INSERT INTO #Temp (selectedValue)
VALUES
    (2)
    , (12)
    , (20)

; WITH
    CTE1 AS
    (
        SELECT id, number_one AS number FROM results
        UNION SELECT id, number_two AS number FROM results
        UNION SELECT id, number_three AS number FROM results
        UNION SELECT id, number_four AS number FROM results
        UNION SELECT id, number_five AS number FROM results
    )
    , CTE2 AS
    (
        SELECT c1.id
        FROM CTE1 c1
            INNER JOIN #Temp t ON c1.number = t.selectedValue
        GROUP BY c1.id
        HAVING COUNT(*) >= (SELECT COUNT(*) AS numberOfSelectedValues FROM #Temp)
    )
SELECT r.*
FROM CTE2 c2
    INNER JOIN results r ON c2.id = r.id
0
Kennah