2012-02-27 7 views
2

私は私の人生のために私がコンポジットキーを返す派生クエリで解決することはできませんが、その内の別のフィールドにMIN()集計関数を実行することはできません非常にイライラのSQLの問題があります表。私は複合キーの1つでMIN()を実行していた場合は簡単ですが、私は両方のキーを返し、MIN()関数を外側のクエリと同様に実行する必要があるため、これを行う方法を考えることができません。クエリ全体は次のようになります。SQLコンポジットキーグループ化の問題

SELECT 
    p.name as productname 
    ,tmp.packageid 
    ,tmp.price 
    ,ppk2.packageoptionid 
    ,ppk2.selcomproductid 
FROM ( 
     SELECT ppk.productid, ppk.packageid, MIN(ppk.price) as price 
     FROM product_package ppk 
       INNER JOIN package pk ON ppk.packageid = pk.id 
       INNER JOIN [plan] pl ON pk.planid = pl.id 
     WHERE pk.networkid = 1 
     GROUP BY ppk.productid, ppk.packageid 
) tmp 
INNER JOIN product_package ppk2 ON ( 
     ppk2.productid = tmp.productid 
    AND ppk2.packageid = tmp.packageid 
)  
INNER JOIN product p ON (p.id = ppk2.productid) 
WHERE p.isenabled = 1; 

現在の結果:

-------------------------------------- 
productid | packageid | price 
1    500    0 
1    501    19.95 
1    502    29.95 
2    501    0 
3    500    15  
3    504    39.95 

望ましい結果:

-------------------------------------- 
productid | packageid | price 
1    500    0 
2    501    0 
3    500    15 

私は独特の必要があるとして、私の問題はどこにあるの導出問合せは "tmpは" あります最も低い価格の各製品/パッケージの組み合わせごとに行を戻してから、外部表に結合してください。

ご協力いただければ幸いです!

+0

良い質問です。今すぐ:[pastebinアカウント](http://pastebin.com/)にサインアップして、stackoverflowがあなたのコードの周りに置くそれらの醜いスライダーバーを見る必要はありませんか? ':)' – Droogans

+1

@Droogansか、コードを書式設定するだけです。 – ninesided

+0

@ninesided:Touche、good sir。 – Droogans

答えて

1

あなたのテーブルに実際に入っているデータはわかりません。私はちょうどあなたのクエリが返すデータを持っています。あなたはあなたのテーブルのデータのサンプルと使用していたDBMSを尋ねる私のコメントに答えなかった。

は、しかし、あなたのテーブルの現在のデータを仮定すると、クエリの出てくる一つであり、次のクエリでは、指定したあなたに「望ましい結果」を与える:表の言葉で

select t1.* from t t1 
left join t t2 
on t1.productid = t2.productid and t1.details > t2.details 
where t2.details is null 

を、この中へ

+-----------+-----------+---------+ 
| PRODUCTID | PACKAGEID | DETAILS | 
+-----------+-----------+---------+ 
|   1 |  500 |  0 | 
|   1 |  501 |  20 | 
|   1 |  502 |  30 | 
|   2 |  501 |  0 | 
|   3 |  500 |  15 | 
|   3 |  504 |  40 | 
+-----------+-----------+---------+ 

:クエリは、このターン、それは明らかだ場合

+-----------+-----------+---------+ 
| PRODUCTID | PACKAGEID | DETAILS | 
+-----------+-----------+---------+ 
|   1 |  500 |  0 | 
|   2 |  501 |  0 | 
|   3 |  500 |  15 | 
+-----------+-----------+---------+ 

は、私を知ってみましょうか否か。

+2

ありがとうMostyは、MIN()関数を実現する興味深い方法であり、明らかに長い時間がかかっているにもかかわらず、特定のフィールドの中で最も低いものです。私は複合キーが返される必要があるとき、MIN()集約と共に2つ以上の値を返すことができるSQL Serverのソリューションがないと思います。ご協力いただきありがとうございます! –

1

簡単な(読み込み:高価な)方法:2つのビューを作成する:のそれぞれがproductid WHERE pk.networkid = 1で、グループがproductidで最小になるもの。それをProduct_MinPrice_VIEWと呼んでください。

はあなただけで作られたProduct_MinPrice_VIEWの結果にINNER JOINを経由してあなたが離れで取得しようとしているすべてのもののサブSELECT INNER JOIN仕事を置き換える2番目のビュー、Product_VIEWを、ビルドします。

私は誓い、SELECTSHAVINGSおよびGROUP-BYは厄介でエラーが発生しやすいと宣誓します。私は時々それに耐えることができません。うまくいけば、これは、後で最適化してより正確にすることができるソリューションを開発するために十分にあなたを得るでしょう。

アプリケーションとFINAL ANSWER

I have an extremely similar problemに私が働いている、との平均時間(私は良い答えのために、このサイトのアップを打つながら)で、私はちょうどバックに合格し、いくつかのアプリケーションレベルを書きました重複を扱うコード、遭遇したときにプログラムのロジックが真の最小値を見つけるようにします。きれいではありませんが、もう一度私は一日中それを把握しようとすることはありません!

私の答えはお手伝いできませんでした。がんばろう!

+0

こんにちはDrooganが応答してくれてありがとう。問題は最小のpackageidではなく、行に影響する最小の価格ですしたがって、製品に複数のパッケージがある場合は、最低価格のパッケージのみを返します。しかし、キャッチは、私はproductid/packageidを返す必要があります。私はグループバイスとサブ選択が特に複数の列がツリーの上に返される必要があり、複数の集計関数が関与する必要がある場合には痛いと思っています:S –

+0

ああ、私は私の答えを更新しますが、 。私の解決策は、本当に答えのデータをあいまいにするかもしれない 'packageid'を完全に切り捨てることです。私はこれ以上調べなければならないでしょう。 – Droogans

+0

これはまさにDroggansの問題に取り組んでいるところであり、私たちはpackageidを削除して喜んでプロダクトIDと最低価格を返すことができますが、そのテーブルにリンクしてさらなるデータにアクセスする能力を失います。私はすべてのデータを最初に戻しますが、これはおそらくMIN(価格)とGROUP BYではありません。また、3レベルの派生クエリーを成功させてみました。私は過去に同様の問題を抱えて頭を浮かべていたことを思い出しているので、このタイプの問題には本当に良い解決策を見つけたことはありません。 –

2

サブクエリが必要なときには、このトリックを使用しました。考え方は、値と鍵を最上位ビットの値と組み合わせて、それを最小にすることです。それから外の選択でそれを取る。

値に結合する最も良い方法は、使用しているRDBMSによって異なります。あなたは私だけの擬似コードを提供していますので、使用しているどちら言及していない:

select ..., (tmp.c >> 32) price 
from 
(select productid, min((price << 32) | packageid) c 
    from product_package 
    where networkid=1 
    group by productid) tmp 
inner join product_package ppk on ppk.productid=tmp.productid 
    and ppk.packageid=(tmp.c & 0xFFFFFFFF) 
inner join product p on p.id=ppk.productid 
where p.isenabled=1 

<< 32手段は、左に値が32ビットをシフトし、|は、ビット単位「または」です。これは、packageidが32ビットの整数(または番号(4))として定義されていると仮定しています。​​はビット単位の "and"と32ビットの16進値で、packageidだけをマスクして返します。

あなたのRDBMSによっては、あなたがこれらの事のためか、彼らはあなたがプレーンな数学を使用することができ、サポートされていませんしている場合、その特定の構文を見つける必要があるかもしれません - << 32あなたの場合は4294967296で割るに4294967296と​​を掛けると同等ですあなたはそれらを組み合わせるためにconvert(binary,price)+convert(binary,packageid)と別々にsubstring(..)を使用することができますMSSQLを使用しています。

+0

おかげさまでゴードーはおもしろいもう一つの答えです。私はMIN()のために一緒に価格とパッケージIDを鋳造するのと似たようなものを試していましたが、それはあまりにも醜いものでした。あなたの方法はよりエレガントで、私はこのシナリオで数学を使うことを考えていませんでした。 –

+0

@PhilRasmussen:クエリの醜さをどのように測定するかによって決まると思いますか?私はこのアプローチの実行計画とあなたが受け入れた回答の実行計画を比較することをお勧めします。あなたが本当にそれをきれいにしたいのであれば、2つのパラメータを取るMinに対してユーザー定義の集計を書くことができます。 – gordy

関連する問題