2011-02-10 10 views
0

名前と値のペアと追加の属性を持つテーブルがあります。同じ名前は複数の値を持つことができます。それが起こる場合は、より高い属性値を持つ行を返したいと思います。Mysqlの一意の値のクエリ

表:クエリの

ID | name | value | attribute 
1 | set1 | 1  | 0 
2 | set2 | 2  | 0 
3 | set3 | 3  | 0 
4 | set1 | 4  | 1 

望ましい結果:

name | value 
set2 | 2 
set3 | 3 
set1 | 4 

望ましい結果を得るための最良の実行SQLクエリとは何ですか?

+0

ん'attribute'の値は重要ですか? – BoltClock

+0

はい、それは難しい部分です。私は最高の属性を持つ行の値を探しているわけではありません。私は内部結合が必要だと思うが、それを書く方法を正確には分かっていない。 – pmm

+0

結婚はどうですか?別の行があるとします(5、set1、5、1)。行4または行5を返す必要がありますか? – Thomas

答えて

0

このソリューションをおそらく最高のパフォーマンスを発揮します:

Select ... 
From Table As T 
    Left Join Table As T2 
     On T2.name = T.name 
      And T2.attribute > T1.attribute 
Where T2.ID Is Null 

perf ORMとしても(あなたがあなたのデータに対して評価する必要があります):

Select ... 
From Table As T 
Where Not Exists (
        Select 1 
        From Table As T2 
        Where T2.name = T.name 
         And T2.attribute > T.attribute 
        ) 
0
select name,max(value) 
from table 
group by name 
+0

これは質問が尋ねることをしません。質問は、最も高い '値'ではなく、最も高い '属性'を持つ行を要求します。 –

0

これを行う簡単な方法はありません。

同様の質問がhereと尋ねられました。

編集:ここで提案です:

SELECT `name`,`value` FROM `mytable` ORDER BY `name`,`attribute` DESC 

これはあなたが求めてかなりのものではないが、それは、少なくとも最初のあなたの高い属性値をあげる、あなたは残りの部分を無視することができます。再び

編集:もう一つの提案:

あなたはvalueは正の整数であることがわかっている場合は、あなたがこれを行うことができます。それはうれしいですが、うまくいくでしょう。

SELECT `name`,CAST (GROUP_CONCAT(`value` ORDER by `attribute` DESC) as UNSIGNED) FROM `mytable` GROUP BY `name` 

あなたはSIGNEDUNSIGNEDを変えることができる負の整数を含めること。

+0

残念ながら値は何でもかまいませんので、これは機能しません。 – pmm

0
SELECT name, value 
FROM (SELECT name, value, attribute 
     FROM table_name 
     ORDER BY attribute DESC) AS t 
GROUP BY name; 
+0

SQL標準では、選択リストの非集計カラム(この場合は 'value')は使用できません。理論的には、MySQLは任意の 'value 'を返すことが許されています。 – awm

+0

私はそれをテストしてうまくいきましたが、今私はawmのコメントで混乱していますので、私はこの答えをチェックしようとしていました。 – pmm

+0

@awm group_concatは集約関数の権利ですか?最初の値を取得するための簡単な文字列操作で、標準に適合させる必要があります。しかし今、私たちは面倒な領域に向かっています。例えば最初のSELECTを "SELECT name、substring_index(group_concat(value)、 '、'、1)を値として変更します。 –

0

これらのオプションをすべてベンチマークすることもできます。別の方法もあります。

SELECT t1.name, t1.value 
    FROM temp t1 
WHERE t1.attribute IN (
    SELECT MAX(t2.attribute) 
    FROM temp t2 
    WHERE t2.name = t1.name); 
+0

+1これはむしろ非効率なクエリですが、これまでのところ実際に尋ねられたことは**唯一の**答えです。 – awm

+1

:D、彼は彼がテーブルを正規化することを提案できました。 – phfeenikz

+0

してください。どのようにテーブルを正規化したら、クエリをどのように実行しますか? – pmm

0

方法について:

SELECT ID, name, value, attribute 
    FROM table A 
WHERE A.attribute = (SELECT MAX(B.attribute) FROM table B WHERE B.NAME = A.NAME); 

編集:誰かがすでに同じことを言ったように思えます。

1

次のように最高性能のクエリは次のようになります。

select 
s.set_id, 
s.name as set_name, 
a.attrib_id, 
a.name as attrib_name, 
sav.value 
from 
sets s 
inner join set_attribute_values sav on 
    sav.set_id = s.set_id and sav.attrib_id = s.max_attrib_id 
inner join attributes a on sav.attrib_id = a.attrib_id 
order by 
s.set_id; 

+--------+----------+-----------+-------------+-------+ 
| set_id | set_name | attrib_id | attrib_name | value | 
+--------+----------+-----------+-------------+-------+ 
|  1 | set1  |   3 | attrib3  | 20 | 
|  2 | set2  |   0 | attrib0  | 10 | 
|  3 | set3  |   0 | attrib0  | 10 | 
|  4 | set4  |   4 | attrib4  | 10 | 
|  5 | set5  |   2 | attrib2  | 10 | 
+--------+----------+-----------+-------------+-------+ 

を明らかに、このために、あなたも、あなたのデザインを正規化し、シンプルなトリガーを実装するつもり持っている仕事に:

drop table if exists attributes; 
create table attributes 
(
attrib_id smallint unsigned not null primary key, 
name varchar(255) unique not null 
) 
engine=innodb; 

drop table if exists sets; 
create table sets 
(
set_id smallint unsigned not null auto_increment primary key, 
name varchar(255) unique not null, 
max_attrib_id smallint unsigned not null default 0, 
key (max_attrib_id) 
) 
engine=innodb; 

drop table if exists set_attribute_values; 
create table set_attribute_values 
(
set_id smallint unsigned not null, 
attrib_id smallint unsigned not null, 
value int unsigned not null default 0, 
primary key (set_id, attrib_id) 
) 
engine=innodb; 

delimiter # 

create trigger set_attribute_values_before_ins_trig 
before insert on set_attribute_values 
for each row 
begin 
    update sets set max_attrib_id = new.attrib_id 
    where set_id = new.set_id and max_attrib_id < new.attrib_id; 
end# 

delimiter ; 

insert into attributes values (0,'attrib0'),(1,'attrib1'),(2,'attrib2'),(3,'attrib3'),(4,'attrib4'); 
insert into sets (name) values ('set1'),('set2'),('set3'),('set4'),('set5'); 

insert into set_attribute_values values 
(1,0,10),(1,3,20),(1,1,30), 
(2,0,10), 
(3,0,10), 
(4,4,10),(4,2,20), 
(5,2,10); 
0

ベンチマークそれらをしなかったが、ここではそれはなんとかです方法です:属性の最大値と テーブル名= TEMM

1)行を:

select t.name, t.value 
from (
    select name, max(attribute) as maxattr 
    from temm group by name 
) as x inner join temm as t on t.name = x.name and t.attribute = x.maxattr; 

最大属性値を持つ2)上位N行:

select name, value 
from temm 
where (
    select count(*) from temm as n 
    where n.name = temm.name and n.attribute > temm.attribute 
) < 1 ; /* 1 can be changed to 2,3,4 ..N to get N rows */ 
関連する問題