2012-02-24 6 views
2

私はすでに以下の問題の解決策を持っていますが、それは愚かで非効率です。SQL:select-where-subquery-returns-oneクエリを改善してください

(id, attributes...)とも問題は正確に一つの対応ThingVersion行が存在Thingから選択することである(id, thing_id, version_attributes...)列を持つThingVersionテーブルとThingテーブルがあります。

私は

SELECT Thing.id AS id, Foo.whatever 
FROM Thing JOIN Foo ON Thing.id=Foo.thing_id 
WHERE Thing.id IN (
    SELECT thing_id FROM ThingVersion TV 
    WHERE 1 = (
     SELECT COUNT(*) 
     FROM ThingVersion TV2 
     WHERE TV2.thing_id = TV.thing_id) 
    ) 
ORDER BY Foo.whatever 

のようなものを持っている現時点では正しい結果を与えているようだ、と強調非第一人者として、それは自明ようだが、 - 選択?!?! - 私は助けることはできませんが、より良い方法が必要であると感じています。

はありますか?

あなたのサブクエリで HAVING句を使用することができます

答えて

2

SELECT Thing.id AS id, Foo.whatever 
    FROM Thing JOIN Foo ON Thing.id=Foo.thing_id 
WHERE Thing.id IN 
     (SELECT thing_id 
      FROM ThingVersion TV 
      GROUP BY thing_id 
      HAVING COUNT(*) = 1 
     ) 
ORDER BY Foo.whatever 
; 

ます。また、メインクエリでJOINを排除することができます

SELECT thing_id AS id, whatever 
    FROM Foo 
WHERE thing_id IN 
     (SELECT thing_id 
      FROM ThingVersion TV 
      GROUP BY thing_id 
      HAVING COUNT(*) = 1 
     ) 
ORDER BY whatever 
; 

(私はそのすべての値を仮定していますFoo.thing_idThingVersion.thing_idの両方に表示されるのは確かにThing.idとなります。

1
SELECT Thing.id AS id, Foo.whatever 
FROM Thing JOIN Foo ON Thing.id=Foo.thing_id 
where Thing.idin (select thing_id from ThingVersion group by thing_id having COUNT(*)>1) 
1

使用してソリューションは、厳密にジョイン:GROUP BYを使用して

SELECT t.* 
FROM Thing t 
JOIN ThingVersion tv1 
    ON tv1.thing_id = t.id 
LEFT JOIN ThingVersion tv2 
    ON tv2.thing_id = t.id 
    AND tv2.id <> tv1.id 
WHERE tv2.id IS NULL 

ソリューションとCOUNT:

SELECT t.* 
FROM Thing t 
JOIN ThingVersion tv 
    ON tv.thing_id = t.id 
GROUP BY t.id 
HAVING COUNT(t.id) = 1; 

をパフォーマンスのためにそれらの両方を試してみてください。

+0

+1ジョインはほとんど確実に 'GROUP BY ... HAVING'ソリューションを実行します。 – GarethD

関連する問題