[英]SQL : find rows and sort according to number of matching columns?
假設我們有一個具有如此簡單結構的“汽車”表...
car_id INT
color ENUM('black','white','blue')
weight ENUM('light','medium','heavy')
type ENUM('van','sedan','limo')
拳頭,我要選擇汽車(1,黑色,重型,豪華轎車),然后我想獲得相關汽車的列表,這些列表按匹配列的數量排序(無任何列重)。 所以,首先我希望看到(黑色,重型,豪華轎車)汽車,然后我希望看到只有2個匹配字段的汽車,等等。
是否可以使用SQL執行這種排序?
對不起,我的英語,但是我真的希望我的問題對您很清楚。
謝謝。
效率不高,但是...
SELECT
exact.car_id AS e_car_id, exact.color AS e_color,
exact.weight AS e_weight, exact.type AS e_type,
related.car_id AS r_car_id, related.color AS r_color,
related.weight AS r_weight, related.type AS r_type,
CASE WHEN related.color = exact.color THEN 1 ELSE 0 END
+ CASE WHEN related.weight = exact.weight THEN 1 ELSE 0 END
+ CASE WHEN related.type = exact.type THEN 1 ELSE 0 END
AS rank
FROM
cars AS exact
INNER JOIN cars AS related ON (
related.car_id <> exact.car_id
AND CASE WHEN related.color = exact.color THEN 1 ELSE 0 END
+ CASE WHEN related.weight = exact.weight THEN 1 ELSE 0 END
+ CASE WHEN related.type = exact.type THEN 1 ELSE 0 END
>= 1
)
WHERE
exact.car_id = 1 /* black, heavy, limo */
ORDER BY
rank DESC
由於JOIN或ORDER BY都不能使用索引,因此在大型數據集上運行速度不會很快。 很可能存在更優化的版本。
我的測試設置上的輸出如下所示:
e_car_id e_color e_weight e_type r_car_id r_color r_weight r_type rank 1 black heavy limo 7 black heavy limo 3 1 black heavy limo 2 black light limo 2 1 black heavy limo 3 black heavy van 2 1 black heavy limo 4 black medium van 1 1 black heavy limo 5 blue light limo 1
可能有幾種方法可以優化子查詢,但是不使用case
語句或次優聯接子句:
select
*
from
(
select
selection.CarId,
selection.Colour,
selection.Weight,
selection.Type,
3 as Relevance
from
tblCars as selection
where
selection.Colour = 'black' and selection.Weight = 'light' and selection.Type = 'van'
union all
select
cars.CarId,
cars.Colour,
cars.Weight,
cars.Type,
count(*) as Relevance
from
tblCars as cars
inner join
(
select
byColour.CarId
from
tblCars as cars
inner join
tblCars as byColour
on
cars.Colour = byColour.Colour
where
cars.Colour = 'black' and cars.Weight = 'light' and cars.Type = 'van'
and
byColour.CarId <> cars.CarId
union all
select
byWeight.CarId
from
tblCars as cars
inner join
tblCars as byWeight
on
cars.Weight = byWeight.Weight
where
cars.Colour = 'black' and cars.Weight = 'light' and cars.Type = 'van'
and
byWeight.CarId <> cars.CarId
union all
select
byType.CarId
from
tblCars as cars
inner join
tblCars as byType
on
cars.Type = byType.Type
where
cars.Colour = 'black' and cars.Weight = 'light' and cars.Type = 'van'
and
byType.CarId <> cars.CarId
) as matches
on
cars.CarId = matches.CarId
group by
cars.CarId,
cars.Colour,
cars.Weight,
cars.Type
) as results
order by
Relevance desc
輸出:
CarId Colour Weight Type Relevance
1 black light van 3
3 white light van 2
4 blue light van 2
5 black medium van 2
6 white medium van 1
7 blue medium van 1
8 black heavy limo 1
我知道這是一個老問題,但是您應該可以將表達式包裝在括號中以對其求值
SELECT *
FROM `cars`
WHERE `color` = "black"
OR `weight` = "heavy"
OR `type` = "limo"
ORDER BY ( (`color` = "black")
+ (`weight` = "heavy")
+ (`type` = "limo")
) DESC
括號內的每個表達式如果為true,則等於1;如果為false,則為0; 因此,總和就是匹配的數量。
mysql> select * from cars;
+--------+-------+--------+-------+
| car_id | color | weight | type |
+--------+-------+--------+-------+
| 1 | black | light | van |
| 2 | black | light | sedan |
| 3 | black | light | limo |
| 4 | black | medium | van |
| 5 | black | medium | sedan |
| 6 | black | medium | limo |
| 7 | black | heavy | van |
| 8 | black | heavy | sedan |
| 9 | black | heavy | limo |
| 10 | white | light | van |
| 11 | white | light | sedan |
| 12 | white | light | limo |
| 13 | white | medium | van |
| 14 | white | medium | sedan |
| 15 | white | medium | limo |
| 16 | white | heavy | van |
| 17 | white | heavy | sedan |
| 18 | white | heavy | limo |
| 19 | blue | light | van |
| 20 | blue | light | sedan |
| 21 | blue | light | limo |
| 22 | blue | medium | van |
| 23 | blue | medium | sedan |
| 24 | blue | medium | limo |
| 25 | blue | heavy | van |
| 26 | blue | heavy | sedan |
| 27 | blue | heavy | limo |
+--------+-------+--------+-------+
27 rows in set (0.00 sec)
select *,
(case
when color = 'black' and weight = 'heavy' and type = 'limo'
then 3
when ( color = 'black' and type = 'limo') or
(color = 'black' and weight = 'heavy') or
(weight = 'heavy' and type = 'limo')
then 2
else 1
end) sort_order
from cars
where color = 'black' or weight = 'heavy' or type = 'limo'
order by sort_order desc;
+--------+-------+--------+-------+------------+
| car_id | color | weight | type | sort_order |
+--------+-------+--------+-------+------------+
| 9 | black | heavy | limo | 3 |
| 27 | blue | heavy | limo | 2 |
| 18 | white | heavy | limo | 2 |
| 8 | black | heavy | sedan | 2 |
| 7 | black | heavy | van | 2 |
| 6 | black | medium | limo | 2 |
| 3 | black | light | limo | 2 |
| 24 | blue | medium | limo | 1 |
| 25 | blue | heavy | van | 1 |
| 21 | blue | light | limo | 1 |
| 26 | blue | heavy | sedan | 1 |
| 17 | white | heavy | sedan | 1 |
| 16 | white | heavy | van | 1 |
| 15 | white | medium | limo | 1 |
| 12 | white | light | limo | 1 |
| 5 | black | medium | sedan | 1 |
| 4 | black | medium | van | 1 |
| 2 | black | light | sedan | 1 |
| 1 | black | light | van | 1 |
+--------+-------+--------+-------+------------+
19 rows in set (0.00 sec)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.