2016-04-30 6 views
0

データベースには、魚の着陸記録を格納する2つのリンクテーブルがあります。ビジネスに必要なのは、これらの着陸に1週間に1回料金が設定され、1週間後に掲示され、支払いが行われて書類のチェックを行うことができる個人を許可することです。このシステムは一般的にうまく機能していたが、先週、ユーザーは何らかの形で記録を変更して、特定の種と魚のサイズに違った価格が設定されたため、他の操作が行われなかった。異なる値を持つ行を識別する最も効率的な方法

これで、追加の検証チェックを追加する必要があります(反復事故の可能性は低いですが)。そのために私はこの問題を複製したいくつかの誤ったデータを考案し、それを取り上げるための最初の単純な部分を設計しました。

これはクエリの最初の部分です。

SELECT DISTINCT 
    ld.ProductId, ld.UnitPrice 
FROM 
    LandingDetails ld 
JOIN 
    LandingHeaders lh ON ld.LandingId = lh.LandingId 
WHERE 
    lh.LandingDate1 BETWEEN '20160313' AND '20160319' 

次に、返されるレコードの種類の例を示します。

enter image description here

があるあなたが見ることができるようにのProductIdの異なる価格で記載されています。この時点から、私はこれを改正して、異なるProductIdと価格を日付期間から戻すのではなく、2つの異なる価格があるProductIdを返すようにしたいと考えています。私が探しているのは、この目標を達成するための最も効率的なSQLの方法です。私は価格を必要としません、私はまだ作成する別の手順で、価格を変更する必要がある製品IDを知るだけで十分です。

答えて

1

最も簡単な方法はHAVING clauseを利用して、外部クエリでクエリをラップすることです:

SELECT q.ProductId 
FROM (
SELECT DISTINCT 
    ld.ProductId, ld.UnitPrice 
FROM 
    LandingDetails ld 
JOIN 
    LandingHeaders lh ON ld.LandingId = lh.LandingId 
WHERE 
    lh.LandingDate1 BETWEEN '20160313' AND '20160319' 
) q 
GROUP BY q.ProductId 
HAVING COUNT(1) >= 2 
+0

シンプルでありがたく、 –

1

使用は異なる価格でIDと一致するすべてのレコードをチェックするために存在します

SELECT DISTINCT ld.ProductId, ld.UnitPrice FROM LandingDetails ld JOIN LandingHeaders lh ON ld.LandingId = lh.LandingId 
WHERE EXISTS (SELECt 1 From LandingDetails ldx WHERE ldx.ProductId = ld.ProductId AND ldx.UnitPrice != ld.UnitPrice) 
+0

(私は常に構文が間違っを取得するように見えるので、大部分が)、私は常に存在言ってきました、ありがとうございますが、頻繁にそれを見落とします。たとえば、私は区切りの日付範囲を取るためにあなたの特定の答えを適応しようとしてきましたが、私のブール比較のエラーを指摘しています。明らかに私はもう少しそれをする必要があります。 –

2
SELECT 
    ld.ProductId 
FROM 
    LandingDetails ld 
JOIN 
    LandingHeaders lh ON ld.LandingId = lh.LandingId 
WHERE 
    lh.LandingDate1 BETWEEN '20160313' AND '20160319' 
GROUP BY ld.ProductId 
HAVING COUNT(DISTINCT ld.UnitPrice)>1 
+1

これは、DISTINCTを使用して受け入れられたソリューションよりも効率的であり(より簡単な構文です) – dnoeth

1

ProductId の両方をご希望の場合は、グループカウント

SELECT * 
FROM 
(
    SELECT -- DISTINCT replaced by GROUP BY, because OVER is processed after GROUP 
     ld.ProductId, ld.UnitPrice, 
     COUNT(*) OVER (PARTITION BY ld.ProductId) AS cnt 
    FROM 
     LandingDetails ld 
    JOIN 
     LandingHeaders lh ON ld.LandingId = lh.LandingId 
    WHERE 
     lh.LandingDate1 BETWEEN '20160313' AND '20160319' 
    GROUP BY 
     ld.ProductId, ld.UnitPrice 
) AS dt 
WHERE cnt > 1 
ORDER BY ld.ProductId, ld.UnitPrice 
関連する問題