3

私はタグシステムに取り組んでいます、それがすべきことはあなたがクエリと選択されたタグを持つことができるということです、例えば、jqueryのタグ。クエリに関連するスクリプトと、タグを持つスクリプトのみを表示する必要があります。これはデータベースのレイアウトです。javascriptlibrary

スクリプトテーブル:

+-----------+---------------+
| script_id | name          |
+-----------+---------------+
|         1 | jQuery        |
|         2 | Sencha Touch  |
|         3 | Codeigniter   |
|         4 | Google Chrome |
|         5 | memcached     |
|         6 | PHP           |
|         7 | MooTools      |
|         8 | node.js       |
|         9 | jQuery Mobile |
+-----------+---------------+

タグテーブル:

+--------+-------------+-------------+
| tag_id | name        | url_name    |
+--------+-------------+-------------+
|      1 | JavaScript  | javascript  |
|      2 | Library     | library     |
|      3 | PHP         | php         |
|      4 | MySQL       | mysql       |
|      5 | Cache       | cache       |
|      6 | HTML        | html        |
|      7 | Open source | open-source |
+--------+-------------+-------------+

タグ付きテーブル:

+-----------+--------+-----------+
| tagged_id | tag_id | script_id |
+-----------+--------+-----------+
|         1 |      1 |         1 |  # javascript -- jQuery
|         2 |      2 |         1 |  # library    -- jQuery
|         3 |      1 |         9 |  # javascript -- jQuery mobile
+-----------+--------+-----------+

SQLを実行すると、それでも検出されますが、タグがjQuery Mobile含まれていないため、SQLが検出されないはずです。選択したタグを満たす必要がある結果を制限するために、SQLが必要です。libraryjQuery

これは私のSQLです:

SELECT scripts.script_id,
       scripts.name
FROM
(
    scripts scripts

    LEFT OUTER JOIN tagged tagged ON tagged.script_id = scripts.script_id

    LEFT OUTER JOIN tags tags ON tags.tag_id = tagged.tag_id
)
WHERE MATCH(scripts.name) AGAINST ('jquery*' IN BOOLEAN MODE) AND ( tags.url_name = 'javascript' OR tags.url_name = 'library' )
GROUP BY script_id
ORDER BY scripts.name
LIMIT 0, 25

それは戻ります:

+-----------+---------------+
| script_id | name          |
+-----------+---------------+
|         1 | jQuery        |
|         9 | jQuery Mobile |
+-----------+---------------+

に変更ORすると、何も返されません。または、タグからAND角かっこを削除しても、何も返されません。()

クエリにタグを制約させるにはどうすればよいですか?

4

4 に答える 4

2

これを試してみてください:

select s.script_id, s.name from scripts s
join tagged tj on s.script_id = tj.script_id
join tags t on t.tag_id = tj.tag_id
where s.name like 'jQuery%' and t.url_name in ('javascript', 'library')
group by s.script_id, s.name
having count(*) = 2
order by s.name
limit 25

これに関する唯一の考慮事項は、節2内の要素の量で置き換える必要があるということです。in

これがフィドルです。

于 2012-04-25T23:54:42.587 に答える
1

ソリューションの主な問題は、結合すると複数の行が作成されることですが、各行には1つのタグ値しかありません。OR条件を使用する場合は、一致したタグのいずれかで十分に返されます。ANDを使用すると、2つの異なる値を持つことができる行はありません。

それらをグループ化するまで、3つの別々の行が生成されます。

+-----------+-----------+---------------+
|     tag_id| script_id | name          |
+-----------+-----------+---------------+
|         1 |         1 | jQuery        |
|         2 |         1 | jQuery        |
|         1 |         9 | jQuery Mobile |
+-----------+-----------+---------------+

これを解決するには、OR条件を使用する必要がありますが、グループの後には、

HAVING count(tag_id) = 2

これにより、SQLに、タグの数に基づいて各グループを評価し、タグが2つだけあるグループのみを残すように指示します。

したがって、コードに基づくソリューションは次のとおりです。

SELECT scripts.script_id,
       scripts.name
FROM
(
    scripts scripts

    LEFT OUTER JOIN tagged tagged ON tagged.script_id = scripts.script_id

    LEFT OUTER JOIN tags tags ON tags.tag_id = tagged.tag_id
)
WHERE MATCH(scripts.name) AGAINST ('jquery*' IN BOOLEAN MODE) AND ( tags.url_name = 'javascript' OR tags.url_name = 'library' )
GROUP BY script_id
HAVING count(tag_id) = 2
ORDER BY scripts.name
LIMIT 0, 25
于 2012-04-24T09:18:09.037 に答える
0

私の試み:

SELECT s.script_id, s.name, so_tags.url_name 
  FROM so_scripts s 
       LEFT JOIN so_tagged USING (script_id) 
       LEFT JOIN so_tags USING (tag_id)
  WHERE s.script_id IN 
  (
    SELECT td.script_id FROM so_tagged td 
      LEFT JOIN so_tags t USING (tag_id) 
    WHERE t.url_name = "javascript" OR t.url_name = "library"
  ) 
GROUP BY url_name HAVING COUNT(s.name) = 2

これはちょっとしたハックです。最初にタグのいずれかに一致するすべてのエントリを検索し、次に名前でグループ化して、指定されたタグの数と一致する数のエントリのみを返します:)

3、4、またはそれ以上のタグの速度はわかりませんが、少なくとも機能します:)

于 2012-04-19T18:53:13.500 に答える
0
SELECT s.script_id,
       s.name
FROM
        scripts AS s
    INNER JOIN 
        tagged AS st1
      ON  st1.script_id = s.script_id
    INNER JOIN tags AS tag1
      ON  tag1.tag_id = st1.tag_id
      AND tag1.url_name = 'javascript'
    INNER JOIN 
        tagged AS st2
      ON  st2.script_id = s.script_id
    INNER JOIN tags AS tag2
      ON  tag2.tag_id = st2.tag_id
      AND tag2.url_name = 'library'
ORDER BY s.name
LIMIT 0, 25
于 2012-04-19T18:43:50.670 に答える