クエリがあります:
SELECT *
FROM Items
WHERE column LIKE '%foo%'
OR column LIKE '%bar%'
結果を並べ替えるにはどうすればよいですか?
「foo」に一致する行と「bar」に一致する行があるが、「foobar」を含む行もあるとしましょう。
最初の結果がより多くの LIKE に一致するものになるように、返された行を並べ替えるにはどうすればよいですか?
ケースまたは 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
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 )
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
を使用できます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
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はありません)
すべての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()を使用して、検索で大文字と小文字を区別しないようにすることもできます。
あなたはこれを試してみたいかもしれません:
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
注: これはドライコード化されており、おそらくあまり移植性がありません。
クエリは現在作成されているため、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 に 3 回一致したか、またはそれらを foo のインスタンスを 1 つしか含まない行の前に並べ替えないかはわかりません。また、これらすべての LIKE は高価になる可能性があります。関連性に基づいて結果を並べ替えたい場合 (どのように定義しても)、全文索引を使用したほうがよい場合があります。MS SQL Server を使用している場合は、これを行うサービスが組み込まれており、同じことを行うサードパーティ製品もあります。
編集:他のすべての回答を見た後(私が始めたときは2つしかありませんでした-明らかに、より速く考える方法を学ぶ必要があります;-))正確に応じて、これについていくつかの方法があることは明らかですあなたが達成しようとしていること。システムでのパフォーマンスに基づいてソリューションをテストおよび比較することをお勧めします. 私はパフォーマンス/チューニングの専門家ではありませんが、特に関数の結果をソートしている場合は、関数によって速度が低下する傾向があります。LIKE 演算子もまた、必ずしも活発であるとは限りません。開発者として、"IF" や "CASE" などの使い慣れた構造を使用するのは自然なことのように思えますが、通常、セットベースのアプローチをより多く使用するクエリは、RDMS でより優れたパフォーマンスを発揮します。繰り返しますが、YMMV ですので、パフォーマンスに関心があるかどうかをテストすることをお勧めします。
どの DBMS ですか?
たとえば、CTE または Union を介して実行できますが、たとえば MySQL を使用している場合は、それを忘れることができます。
このコードを試してください:
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