2010-12-07 82 views
4

使用下面的表作爲示例並將列出的查詢作爲基本查詢,我想添加一種方法來僅選擇具有最大ID的行!無需做第二次查詢!MySQL選擇具有最大ID並匹配其他條件的行

TABLE VEHICLES 

id  vehicleName 
----- -------- 
1  cool car 
2  cool car 
3  cool bus 
4  cool bus 
5  cool bus 
6  car 
7  truck 
8  motorcycle 
9  scooter 
10  scooter 
11  bus 

TABLE VEHICLE NAMES 

nameId vehicleName 
------ ------- 
1  cool car 
2  cool bus 
3  car 
4  truck 
5  motorcycle 
6  scooter 
7  bus 

TABLE VEHICLE ATTRIBUTES 

nameId attribute 
------ --------- 
1  FAST 
1  SMALL 
1  SHINY 
2  BIG 
2  SLOW 
3  EXPENSIVE 
4  SHINY 
5  FAST 
5  SMALL 
6  SHINY 
6  SMALL 
7  SMALL 

而且基本查詢:

select a.* 
    from vehicle   a 
    join vehicle_names b using(vehicleName) 
    join vehicle_attribs c using(nameId) 
where c.attribute in('SMALL', 'SHINY') 
and a.vehicleName like '%coo%' 
group 
    by a.id 
having count(distinct c.attribute) = 2; 

所以我想實現的是選擇具有某些屬性列,其中ID是匹配的名字,但對於每個匹配名稱只有一個條目最高!

因此,在本例中,工作液將返回以下行:

id  vehicleName 
----- -------- 
2  cool car 
10  scooter 

,如果它是目前使用某種最大的對ID

我得到的所有條目涼車和滑板車。

我的真實世界的數據庫遵循類似的結構,並有數以萬計的條目,所以像上面這樣的查詢可以很容易地返回3000+的結果。我將結果限制爲100行,以便將結果用於搜索我的網站時保持較低的執行時間。我重複同名的「車輛」,但只有一個不同的ID的原因是新車型不斷添加,但我保留那些想要挖掘它們的舊車型!但是,在搜索汽車名稱時,我不想將舊卡僅更換爲ID最高的卡!

正確的答案將適應我上面提供的查詢,我目前正在使用它,並讓它只返回名稱匹配但行號最高的行!

如果這是不可能的,不用大量增加搜索的執行時間,我就可以達到我想要的效果。

+0

你對'(填充NameID,屬性)``上指數vehicle_attribs`?而在使用`LIKE「%酷%」 vehicle_names搜索`不使用任何索引 – ajreal 2010-12-08 12:26:31

+0

@ajreal有在vehicle_attribs上(填充NameID,屬性)主鍵。 – Tristan 2010-12-08 13:40:27

回答

4

如果你想讓你的邏輯,在這裏我會做什麼:

select a.* 
from vehicle a 
    left join vehicle a2 on (a.vehicleName = a2.vehicleName and a.id < a2.id) 
    join vehicle_names b on (a.vehicleName = b.vehicleName) 
    join vehicle_attribs c using(nameId) 
where c.attribute in('SMALL', 'SHINY') 
    and a.vehicleName like '%coo%' 
    and a2.id is null 
group by a.id 
having count(distinct c.attribute) = 2;

其產生:

+----+-------------+ 
| id | vehicleName | 
+----+-------------+ 
| 2 | cool car | 
| 10 | scooter  | 
+----+-------------+ 
2 rows in set (0.00 sec) 

至於對方說,標準化可以在幾級完成

維持目前的vehicle_names表作爲主查找表,我會改變:

update vehicle a 
    inner join vehicle_names b using (vehicleName) 
set a.vehicleName = b.nameId; 
alter table vehicle change column vehicleName nameId int; 

create table attribs (
    attribId int auto_increment primary key, 
    attribute varchar(20), 
    unique key attribute (attribute) 
); 
insert into attribs (attribute) 
    select distinct attribute from vehicle_attribs; 
update vehicle_attribs a 
    inner join attribs b using (attribute) 
set a.attribute=b.attribId; 
alter table vehicle_attribs change column attribute attribId int; 

這就導致了下面的查詢:

select a.id, b.vehicleName 
from vehicle a 
    left join vehicle a2 on (a.nameId = a2.nameId and a.id < a2.id) 
    join vehicle_names b on (a.nameId = b.nameId) 
    join vehicle_attribs c on (a.nameId=c.nameId) 
    inner join attribs d using (attribId) 
where d.attribute in ('SMALL', 'SHINY') 
    and b.vehicleName like '%coo%' 
    and a2.id is null 
group by a.id 
having count(distinct d.attribute) = 2;
3

表似乎並不歸,但是這有助於你這樣做:

select max(id), vehicleName 
from VEHICLES 
group by vehicleName 
having count(*)>=2; 
+0

該表只是一個與真實情況完全不同的示例!這個羣體對最大值是重要的嗎?但是,我真正在回答的是什麼,我會添加到我上面提供的查詢來選擇只有最大行!由於 – Tristan 2010-12-07 22:13:04

1

我不知道我完全理解你的模型,但是當他們站在下面的查詢滿足您的要求。第一個子查詢查找車輛的最新版本。第二個查詢滿足您的「和」條件。然後,我只是加入關於vehiclename的查詢(這是關鍵?)。

select a.id 
     ,a.vehiclename 
    from (select a.vehicleName, max(id) as id 
      from vehicle a 
     where vehicleName like '%coo%' 
     group by vehicleName 
     ) as a 
    join (select b.vehiclename 
      from vehicle_names b 
      join vehicle_attribs c using(nameId) 
     where c.attribute in('SMALL', 'SHINY') 
     group by b.vehiclename 
     having count(distinct c.attribute) = 2 
     ) as b on (a.vehicleName = b.vehicleName); 

如果這個「最新的車輛」的邏輯是你需要做很多,一個小建議是創建一個視圖(見下文),它返回的最新版本每輛車的。然後,您可以使用視圖而不是find-max-query。請注意,這純粹是爲了易用性,它不提供性能優勢。

select * 
    from vehicle a 
where id = (select max(b.id) 
       from vehicle b 
       where a.vehiclename = b.vehiclename); 
+0

意見沒有索引,所以它可能不會加速與記錄的OP擁有量查詢結果。 – Danosaure 2010-12-12 15:14:33

+0

@Danosaure:我將修改我的答案更清楚地表明我的建議是爲了提高易用性。 – Ronnis 2010-12-12 19:26:47

0

沒有進入正確的重新設計的模型,你,你可以

1)添加列IsLatest您的應用程序可以管理。

這不是完美的,但將滿足你的問題(直到下一個問題,看到沒底) 所有你需要的是,當你添加新條目在一個事務中發出查詢,如

UPDATE a 
SET IsLatest = 0 
WHERE IsLatest = 1 

INSERT new a 

UPDATE a 
SET IsLatest = 1 
WHERE nameId = @last_inserted_id 

或觸發

2)您也可以找出max_id您發出前查詢

SELECT MAX(nameId) 
FROM a 
WHERE vehicleName = @name 

3)您可以在單一做吧QL,並提供有關(vehicleName,填充NameID)指標,它實際上應該有不錯的速度

select a.* 
    from vehicle   a 
    join vehicle_names b ON a.vehicleName = b.vehicleName 
    join vehicle_attribs c ON b.nameId = c.nameId AND c.attribute = 'SMALL' 
    join vehicle_attribs d ON b.nameId = c.nameId AND d.attribute = 'SHINY' 
    join vehicle   notmax ON a.vehicleName = b.vehicleName AND a.nameid < notmax.nameid 
where a.vehicleName like '%coo%' 
     AND notmax.id IS NULL 

我已刪除了您的GROUP BY和HAVING與另一個替換它連接(假設每次填充NameID只有單一的屬性是可能的) 。

我還用的找每組最多的一種方式,那就是加入本身的表和篩選出一排它沒有記錄有一個同名的更大的ID。

還有其他的方法,對「每組最多的SQL」搜索等等。另請參閱here,雖然不完整。

相關問題