1


0

SELECTステートメントのサポートが必要

次のように、レコードとレコードに添付できる検索タグの関係を表現します。

TABLE RECORDS
id
name

TABLE SEARCHTAGS
id
recordid
name

私は彼らが持っている検索タグに基づいてレコードを選択できるようにしたい。 たとえば、検索タグを持つすべてのレコードを選択できるようにしたい:

(1 OR 2 OR 5) AND (6 OR 7) AND (10)

上記のデータ構造を使用すると、これを実現するためにSQLをどのように構造化するかがわかりません。

助言がありますか?

ありがとうございます。

6 Answer


2


次のことを試してください。

SELECT    r.id, r.name
FROM      records r
WHERE     EXISTS (SELECT NULL FROM searchtags WHERE recordid = r.id AND id IN (1, 2, 5)) AND
          EXISTS (SELECT NULL FROM searchtags WHERE recordid = r.id AND id IN (6, 7)) AND
          EXISTS (SELECT NULL FROM searchtags WHERE recordid = r.id AND id IN (10));

テストケース:レコード1と4のみがクエリ基準を満たすことに注意してください。

CREATE TABLE records (id int, name varchar(10));
CREATE TABLE searchtags (id int, recordid int);

INSERT INTO records VALUES (1, 'a');
INSERT INTO records VALUES (2, 'b');
INSERT INTO records VALUES (3, 'c');
INSERT INTO records VALUES (4, 'd');

INSERT INTO searchtags VALUES (1,  1);
INSERT INTO searchtags VALUES (2,  1);
INSERT INTO searchtags VALUES (6,  1);
INSERT INTO searchtags VALUES (10, 1);
INSERT INTO searchtags VALUES (1,  2);
INSERT INTO searchtags VALUES (2,  2);
INSERT INTO searchtags VALUES (3,  2);
INSERT INTO searchtags VALUES (1,  3);
INSERT INTO searchtags VALUES (10, 3);
INSERT INTO searchtags VALUES (5,  4);
INSERT INTO searchtags VALUES (7,  4);
INSERT INTO searchtags VALUES (10, 4);

結果:

+------+------+
| id   | name |
+------+------+
|    1 | a    |
|    4 | d    |
+------+------+
2 rows in set (0.01 sec)


1


SELECT
  id, name
FROM
  records
WHERE
  EXISTS (
    SELECT 1 FROM searchtags WHERE recordid = records.id AND id IN (1, 2, 5)
  )
  AND EXISTS (
    SELECT 1 FROM searchtags WHERE recordid = records.id AND id IN (6, 7)
  )
  AND EXISTS (
    SELECT 1 FROM searchtags WHERE recordid = records.id AND id IN (10)
  )


0


mysqlでそれを行う方法はわかりませんが、t-sqlでは次のようなことができます。

SELECT id, name FROM RECORDS where id in (SELECT recordid from SEARCHTAGS where id in (1,2,5,6,7,10))

私はあなたの質問を完全に理解していないかもしれません…​ でもベストを尽くしました。


0


Try:

SELECT R.*
FROM RECORDS R, SEARCHTAGS S
WHERE R.id == S.recordid
AND S.name in (1,2,5,6,7,10);

S.nameまたはS.idが必要かどうかわかりませんが、これは一例です。


0


 select RECORDS.name
    from RECORDS join SEARCHTAGS
    on RECORDS.id = SEARCHTAGS.recordid
    where RECORDS.id in (1,2,...)


0


私は最初に質問を誤解し、それが求めていると思った

(1 AND 2 AND 5) OR (6 AND 7) OR (10)

正しいのではなく

(1 OR 2 OR 5) AND (6 OR 7) AND (10)

これまでのすべての答えは、より一般的な質問「そして次回は別の基準セットが必要だと仮定する」ではなく、特定の例に答えることに集中しています。

実際の質問

実際の質問に対して選択した回答よりもはるかに良い結果を出すことはできません(*クエリ1 *):

SELECT r.id, r.name
  FROM Records AS r
 WHERE EXISTS(SELECT * FROM SearchTags AS s
               WHERE r.id = s.recordid AND s.id IN (1, 2, 5))
   AND EXISTS(SELECT * FROM SearchTags AS s
               WHERE r.id = s.recordid AND s.id IN (6, 7))
   AND EXISTS(SELECT * FROM SearchTags AS s
               WHERE r.id = s.recordid AND s.id IN (10));

これは、SearchTagsテーブルの3つのエイリアスへの結合として記述できます。

別の質問

代替案に答えるにはいくつかの方法があります-これは最もきちんとしていて拡張可能だと思います。 明らかに、1つの項目(10)は簡単です(*クエリ2 *):

SELECT r.id, r.name
  FROM records AS r JOIN searchtags AS t ON r.id = t.recordid
 WHERE t.id IN (10)  -- or '= 10' but IN is consistent with what follows

2つの項目(6または7)は(* Query 3 *)で実行できます。

SELECT r.id, r.name
  FROM records AS r JOIN searchtags AS t ON r.id = t.recordid
 WHERE t.id IN (6, 7)
 GROUP BY r.id, r.name
HAVING COUNT(*) = 2

3つの項目(1、2、5)は(* Query 4 *)で実行できます。

SELECT r.id, r.name
  FROM records AS r JOIN searchtags AS t ON r.id = t.recordid
 WHERE t.id IN (1, 2, 5)
 GROUP BY r.id, r.name
HAVING COUNT(*) = 3

また、コレクション全体が3つの用語のUNIONになります。

ソリューションの一般化

このソリューションの欠点は、アイテムのセットごとにSQLを手動で作成する必要があることです。 「SQL生成」を自動化する場合は、テーブル内のコントロールデータ(興味深い検索タグのセット)が必要です。

CREATE TABLE InterestingTags(GroupID INTEGER, TagID INTEGER);
INSERT INTO InterestingTags(1, 1);
INSERT INTO InterestingTags(1, 2);
INSERT INTO InterestingTags(1, 5);
INSERT INTO InterestingTags(2, 6);
INSERT INTO InterestingTags(2, 7);
INSERT INTO InterestingTags(3, 10);

'(1 OR 2 OR 5)AND(…​)'(接続標準形)を求めるクエリの場合、次のように記述できます(* Query 5 *):

SELECT r.id, r.name
  FROM records AS r JOIN
       searchtags AS s ON r.id = s.recordID JOIN
       interestingtags AS t ON s.id = t.tagID
 GROUP BY r.id, r.name
HAVING COUNT(DISTINCT t.GroupID) = (SELECT COUNT(DISTINCT GroupID)
                                      FROM InterestingTags);

これにより、特定のレコードの個別の「タグの興味深いグループ」の数が「タグの興味深いグループ」の総数に等しいことがチェックされます。

'(1 AND 2 AND 5)OR(…​)'(選言標準形式)を要求するクエリの場合、InterestingTagsを使用して結合を記述し、レコードにタグのグループと同じ数のエントリがあることを確認できます(* Query 6 *):

SELECT i.id, i.name
  FROM (SELECT q.id, q.name, c.GroupSize,
               COUNT(DISTINCT t.GroupID) AS GroupCount
          FROM records AS q JOIN
               searchtags AS s ON q.id = s.recordID JOIN
               interestingtags AS t ON s.id = t.tagID JOIN
               (SELECT GroupID, COUNT(*) AS GroupSize
                  FROM InterestingTags
                 GROUP BY GroupID) AS c ON c.GroupID = t.GroupID
         GROUP BY q.id, q.name, c.GroupSize
       ) AS i
 WHERE i.GroupCount = i.GroupSize;

テストデータ

Daniel Vassaloの回答からテストデータを取得し、追加の値を追加しました。

CREATE TABLE records (id int, name varchar(10));
CREATE TABLE searchtags (id int, recordid int);

INSERT INTO records VALUES (1, 'a');
INSERT INTO records VALUES (2, 'b');
INSERT INTO records VALUES (3, 'c');
INSERT INTO records VALUES (4, 'd');

INSERT INTO records VALUES (11, 'A11');
INSERT INTO records VALUES (21, 'B12');
INSERT INTO records VALUES (31, 'C13');
INSERT INTO records VALUES (41, 'D14');
INSERT INTO records VALUES (51, 'E15');
INSERT INTO records VALUES (61, 'F16');

INSERT INTO searchtags VALUES (1,  1);
INSERT INTO searchtags VALUES (2,  1);
INSERT INTO searchtags VALUES (6,  1);
INSERT INTO searchtags VALUES (10, 1);
INSERT INTO searchtags VALUES (1,  2);
INSERT INTO searchtags VALUES (2,  2);
INSERT INTO searchtags VALUES (3,  2);
INSERT INTO searchtags VALUES (1,  3);
INSERT INTO searchtags VALUES (10, 3);
INSERT INTO searchtags VALUES (5,  4);
INSERT INTO searchtags VALUES (7,  4);
INSERT INTO searchtags VALUES (10, 4);

INSERT INTO searchtags VALUES (1,  11);
INSERT INTO searchtags VALUES (2,  11);
INSERT INTO searchtags VALUES (5,  11);
INSERT INTO searchtags VALUES (6,  21);
INSERT INTO searchtags VALUES (7,  21);
INSERT INTO searchtags VALUES (10, 31);
INSERT INTO searchtags VALUES (1,  41);
INSERT INTO searchtags VALUES (6,  41);
INSERT INTO searchtags VALUES (10, 41);
INSERT INTO searchtags VALUES (2,  51);
INSERT INTO searchtags VALUES (5,  51);
INSERT INTO searchtags VALUES (10, 51);
INSERT INTO searchtags VALUES (7,  61);
INSERT INTO searchtags VALUES (2,  61);
INSERT INTO searchtags VALUES (1,  61);

CREATE TABLE InterestingTags(GroupID INTEGER, TagID INTEGER);
INSERT INTO InterestingTags VALUES(1, 1);
INSERT INTO InterestingTags VALUES(1, 2);
INSERT INTO InterestingTags VALUES(1, 5);
INSERT INTO InterestingTags VALUES(2, 6);
INSERT INTO InterestingTags VALUES(2, 7);
INSERT INTO InterestingTags VALUES(3, 10);

試験結果

私が得た出力は次のとおりです。

*クエリ1 *

1   a
4   d
41  D14

*クエリ2 *

1   a
3   c
4   d
31  C13
41  D14
51  E15

*クエリ3 *

21  B12

*クエリ4 *

11  A11

*クエリ5 *

1   a
41  D14
4   d

*クエリ6 *

4   d
31  C13
3   c
1   a
41  D14
51  E15

明らかに、特定の順序で出力が必要な場合は、クエリにORDER BY句を追加します。