2

クエリがあります:

SELECT *
FROM Items
WHERE column LIKE '%foo%'
   OR column LIKE '%bar%'

結果を並べ替えるにはどうすればよいですか?

「foo」に一致する行と「bar」に一致する行があるが、「foobar」を含む行もあるとしましょう。

最初の結果がより多くの LIKE に一致するものになるように、返された行を並べ替えるにはどうすればよいですか?

4

10 に答える 10

4

ケースまたは RDBMS がサポートする条件構造の種類は、それを行う方法です。

select *, case when col like '%foo%' and col like '%bar%' then 2 end 
else 1 end as ordcol 
from items 
where col like '%foo%' or col like '%bar%' order by ordcol
于 2008-09-17T02:43:43.147 に答える
2
SELECT * FROM Items WHERE column LIKE '%foo%' OR column LIKE '%bar%' 
ORDER BY 
(IF(column LIKE '%foo%',1,0) + IF(column LIKE '%bar%',1,0)) 
DESC

if の構文は

IF ( condition, true_value, false_value )

于 2008-09-17T02:48:10.577 に答える
1
SELECT * FROM Items
WHERE col LIKE '%foo%'
    OR col LIKE '%bar%'
ORDER BY CASE WHEN col LIKE '%foo%' THEN 1
                WHEN col LIKE '%bar%' THEN 2
            END
于 2008-09-17T10:21:25.883 に答える
1

を使用できますUNION

SELECT * FROM Items WHERE column LIKE '%foo%' AND column LIKE '%bar%'
UNION
SELECT * FROM Items WHERE column LIKE '%foo%' AND NOT (column LIKE '%bar%')
UNION
SELECT * FROM Items WHERE column LIKE '%bar%' AND NOT (column LIKE '%foo%');

しかし、これはパフォーマンス面で悪いかもしれません。さらに悪いことに、これを使用して、最初に最も意味のある結果を提供する検索エンジンを構築し、次に単語数が 2 に制限されないようにしたいと考えています。

その場合、score一致数を含む列を作成できます。このようなもの:

SELECT
    *,
    (IF(column LIKE '%bar%', 1, 0) + IF(column LIKE '%foo%', 1, 0)) AS score
FROM Items
WHERE column LIKE '%foo%' OR column LIKE '%bar%'
ORDER BY score DESC;

私の SQL は少しさびていますが、少なくとも MySQL 5.0 ではこのようなことが可能になるはずです。関数のマニュアルも参照してくださいIF: http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html

于 2008-09-17T02:47:08.987 に答える
0

2つのクエリ:

SELECT * FROM Items WHERE column LIKE '%foo%' AND column LIKE '%bar%';
SELECT * FROM Items WHERE (column LIKE '%foo%' AND column NOT LIKE '%bar%') OR (column NOT LIKE '%foo%' AND LIKE '%bar%')

(SQLにはXORはありません)

于 2008-09-17T02:55:53.583 に答える
0

すべてのRDBMSがIF(またはOracleのDECODE)ステートメントをサポートしているわけではありません。そうでない場合は、サブクエリを使用してテーブル "a"を定義し、すべての従業員の名前付きJOSMITHまたはその組み合わせを検索できます。

SELECT 
 a.employee_id,
 a.surname,
 sum(a.counter)
FROM

 (SELECT
   employee_id,
   surname,
   1 as counter
  FROM
   MyTable
  WHERE
   surname like '%SMITH%'

  UNION ALL

  SELECT
   employee_id,
   surname,
   1 as counter
  FROM
   MyTable
  WHERE
   surname like '%JO%'
   ) a

GROUP BY 
 a.employee_id,
 a.surname
ORDER BY 3,1,2

UNION ALLを使用していることを確認してください。そうしないと、機能しません。また、UPPER()を使用して、検索で大文字と小文字を区別しないようにすることもできます。

于 2008-09-17T03:00:04.073 に答える
0

あなたはこれを試してみたいかもしれません:

SELECT *
FROM Items
WHERE column LIKE '%foo%' OR column LIKE '%bar%'
ORDER BY CASE WHEN column LIKE '%foo%' AND column LIKE '%bar%' THEN 1 ELSE 0 END DESC

注: これはドライコード化されており、おそらくあまり移植性がありません。

于 2008-09-17T02:46:12.983 に答える
0

クエリは現在作成されているため、WHERE 句は結果の並べ替えに使用できる情報を提供しません。私はブライアンのアイデアが好きです。定数列を追加し、クエリを UNION すると、1 つの結果セットですべてを取得することもできます。例えば:

SELECT 1 as rank, * FROM Items WHERE column LIKE '%foo%' AND column LIKE '%bar%'
UNION
SELECT 2 as rank, * FROM Items WHERE column LIKE '%foo%' AND column NOT LIKE '%bar%'
UNION
SELECT 2 as rank, * FROM Items WHERE column LIKE '%bar%' AND column NOT LIKE '%foo%'
ORDER BY rank

ただし、これは次のようなものしか提供しません。

  • foo と match bar に一致するすべての行の順序付けられていないセット
  • その後に、foo または bar の両方ではなく一致するすべての行 (の順序付けられていないセット) が続きます (ただし、最後の SELECT ステートメントで異なる定数を使用して、これを 2 つの別個のグループに分割できます)。

これはまさにあなたが探しているものかもしれませんが、どの行が foo に 3 回一致したか、またはそれらを foo のインスタンスを 1 つしか含まない行の前に並べ替えないかはわかりません。また、これらすべての LIKE は高価になる可能性があります。関連性に基づいて結果を並べ替えたい場合 (どのように定義しても)、全文索引を使用したほうがよい場合があります。MS SQL Server を使用している場合は、これを行うサービスが組み込まれており、同じことを行うサードパーティ製品もあります。

編集:他のすべての回答を見た後(私が始めたときは2つしかありませんでした-明らかに、より速く考える方法を学ぶ必要があります;-))正確に応じて、これについていくつかの方法があることは明らかですあなたが達成しようとしていること。システムでのパフォーマンスに基づいてソリューションをテストおよび比較することをお勧めします. 私はパフォーマンス/チューニングの専門家ではありませんが、特に関数の結果をソートしている場合は、関数によって速度が低下する傾向があります。LIKE 演算子もまた、必ずしも活発であるとは限りません。開発者として、"IF" や "CASE" などの使い慣れた構造を使用するのは自然なことのように思えますが、通常、セットベースのアプローチをより多く使用するクエリは、RDMS でより優れたパフォーマンスを発揮します。繰り返しますが、YMMV ですので、パフォーマンスに関心があるかどうかをテストすることをお勧めします。

于 2008-09-17T03:19:06.743 に答える
0

どの DBMS ですか?

たとえば、CTE または Union を介して実行できますが、たとえば MySQL を使用している場合は、それを忘れることができます。

于 2008-09-17T02:41:10.250 に答える
0

このコードを試してください:

SELECT * FROM Items WHERE column LIKE '%foo%' OR column LIKE '%bar%'
order by (select count(*) from items i where i.column= item.column) DESC 

詳細を気にしない場合は、 とcolumnでグループ化することもできます。count(*)ORDER

于 2008-09-17T02:43:56.483 に答える