1

変更する必要があるクエリがあります。クエリが現在行っていることは、広告のタイトルと広告の説明に基づいて検索結果 (広告) を返すことです。いずれかの検索語が広告のタイトルまたは広告の説明で見つかった場合、それらの結果が返されます

各広告が特定の広告タイトルに対して 1 回だけ検索結果に表示されるようにクエリを変更したい...したがって、検索で特定の単語に対して同じ広告タイトルを持つ 5 つの広告が見つかった場合、1 つの広告のみが返されるはずです。その広告タイトルに...

$sql = "SELECT a.*, UNIX_TIMESTAMP(a.createdon) AS timestamp, ct.cityname,
                    COUNT(*) AS piccount, p.picfile,
                    scat.subcatname, cat.catid, cat.catname $xfieldsql
                FROM t_ads a
                    INNER JOIN t_cities ct ON a.cityid = ct.cityid
                    INNER JOIN t_subcats scat ON a.subcatid = scat.subcatid
                    INNER JOIN t_cats cat ON scat.catid = cat.catid
                    LEFT OUTER JOIN t_adxfields axf ON a.adid = axf.adid
                    LEFT OUTER JOIN t_adpics p ON a.adid = p.adid AND p.isevent = '0'
                    LEFT OUTER JOIN t_featured feat ON a.adid = feat.adid AND feat.adtype = 'A'
                WHERE $where
                    AND $visibility_condn
                    AND (feat.adid IS NULL OR feat.featuredtill < NOW())
                    $loc_condn
                GROUP BY a.adid
                ORDER BY a.createdon DESC
                LIMIT $offset, $ads_per_page";

編集: $where には検索式が含まれています...正規表現検索が有効になっている場合は正規表現を使用します。それ以外の場合は無効です... $sqlsearch にはユーザーが入力した検索語が含まれています...

if ($regex_search) {
                $where = "(a.adtitle RLIKE '[[:<:]]{$searchsql}[[:>:]]' OR a.addesc RLIKE '[[:<:]]{$searchsql}[[:>:]]')";
            } else {
                $where = "(a.adtitle LIKE '$searchsql' OR a.addesc LIKE '$searchsql')";
4

1 に答える 1

3

これを行うための「適切な」方法は、最初に重複が表示される理由を解明して、ルートの原因に取り組むことです。JOINと関係がありますが、データを見ないと答えられません。ただし、重複を削除するための迅速な(っぽい)汚い方法が必要な場合は、以下のようなものを試すことができます。

免責事項:これは完全にテストされていないため、ここに 1 つまたは 2 つの間違いがある可能性が高くなりますが、問題が発生しないことを願っています。

SELECT a2.*, UNIX_TIMESTAMP(a.createdon) AS timestamp, ct2.cityname,
       COUNT(*) AS piccount, p2.picfile,
       scat2.subcatname, cat2.catid, cat2.catname $xfieldsql
FROM
   (SELECT subq1.title, MIN(subq1.adid) AS adid
    FROM 
           (SELECT a.*, UNIX_TIMESTAMP(a.createdon) AS timestamp, ct.cityname,
                COUNT(*) AS piccount, p.picfile,
                scat.subcatname, cat.catid, cat.catname
            FROM t_ads a
                INNER JOIN t_cities ct ON a.cityid = ct.cityid
                INNER JOIN t_subcats scat ON a.subcatid = scat.subcatid
                INNER JOIN t_cats cat ON scat.catid = cat.catid
                LEFT OUTER JOIN t_adxfields axf ON a.adid = axf.adid
                LEFT OUTER JOIN t_adpics p ON a.adid = p.adid AND p.isevent = '0'
                LEFT OUTER JOIN t_featured feat ON a.adid = feat.adid AND feat.adtype = 'A'
            WHERE $where
                AND $visibility_condn
                AND (feat.adid IS NULL OR feat.featuredtill < NOW())
                $loc_condn
            GROUP BY a.adid) subq1
    GROUP BY subq.title) subq2
INNER JOIN t_ads a2 ON a2.adid = subq2.adid
INNER JOIN t_cities ct2 ON a2.cityid = ct2.cityid
INNER JOIN t_subcats scat2 ON a2.subcatid = scat2.subcatid
INNER JOIN t_cats cat2 ON scat2.catid = cat2.catid
LEFT OUTER JOIN t_adxfields axf2 ON a2.adid = axf2.adid
LEFT OUTER JOIN t_adpics p2 ON a2.adid = p2.adid AND p2.isevent = '0'
LEFT OUTER JOIN t_featured feat2 ON a2.adid = feat2.adid AND feat2.adtype = 'A'
ORDER BY a2.createdon DESC
LIMIT $offset, $ads_per_page

これは、サブクエリからいくつかのものを削除するなどして、大幅に単純化して整理することができますが、(できれば) 起動して実行するための一般的なアイデアを提供しているだけです...

説明

subq2単にタイトルでグループ化し、adid各グループから を選択します (MINここで使用することを選択しましたが、MAX代わりに使用することもできました)。

subq1は元のクエリですが、順序と制限は外側のクエリによって適用されるため削除されています。

外側のクエリは、元のクエリからフィールドを選択するために、重複除去された ID に結合し、広告や他のテーブルに結合し直します (それらに異なるエイリアスを与えます)。

于 2013-04-17T19:52:26.270 に答える