2017-05-25 3 views
-1

私はコンテンツMYSQL相互に異なる列

コンテンツは、CONTENT_ID android_idと私は特定のCONTENT_ID

のために明確なandroid_idとUSER_IDの数を選択したい

content_id | android_id | user_id  
    a1   | b1  | c1 
    a1   | b2  | c2 
    a1   | b3  | c1 
    a1   | b4  | c3 
    a1   | b1  | c4 
    a2   | b2  | c1 

をUSER_IDたという名前のテーブルを持っています

(特定のandroid_idがいずれかの行に表示されている場合、user_idが異なる場合でも他の行には表示されない、user_idの場合と同様に選択された行のuser_idは一致しない)

CONTENT_ID = A1ためすなわち、行が

a1   | b1  | c1 
a1   | b2  | c2 
a1   | b4  | c3 

すなわちB1、C1、B2、C2、B4を選択すべきである以下、C3は互いに別個であり、複数の行のいずれか

に表示されませんでしたMYSQLクエリが欲しいです。おかげでロジックをクリアするためのクリス・リアのおかげで

+1

これまでに何を試みましたか?試した質問を表示してください。 – Styphon

+1

私はあなたの要件を理解していません。 –

+0

どちらか分かりません。どうして 'a1 | b3 | 「c1」が選択されていますか? –

答えて

1

行を並べ替える列がidであると仮定すると、望ましい結果が得られます。

SELECT COUNT(*) 
FROM content AS c1 
LEFT JOIN content AS c2 
ON c1.content_id = c2.content_id AND c1.id > c2.id 
AND (c1.android_id = c2.android_id OR c1.user_id = c2.user_id) 
WHERE c1.content_id = 'a1' AND c2.id IS NULL 

別のテーブルに一致しない行を見つけるために、通常のLEFT JOIN/NULLパターンに基づいています。この場合、他のテーブルは同じテーブルであり、c1.id > c2.idは、テーブル内の最初の行を排他的なセットに戻します。結合条件は、android_iduser_idの両方をテストします。いずれかが一致すると、結果から除外されます。

DEMO

+0

私はsqlfiddleのUIが好きですが、rextesterがはるかに高速であることを認めなければなりません。 – Strawberry

+0

@Strawberry True、sqlfiddleは古い習慣です。 – Barmar

+0

rextesterの欠点はもちろん、FKの制約を受けていないテーブルネームを見つける必要があるということです.-( – Strawberry

0

...

DROP TABLE IF EXISTS my_table; 

CREATE TABLE my_table 
(content_id INT NOT NULL 
,android_id INT NOT NULL 
,user_id INT NOT NULL 
,PRIMARY KEY(content_id,android_id,user_id) 
); 

INSERT INTO my_table VALUES 
(1, 1, 1), 
(1, 2, 2), 
(1, 3, 1), 
(1, 4, 3), 
(1, 1, 4), 
(2, 2, 1); 

SELECT x.* 
    FROM my_table x 
    LEFT 
    JOIN my_table y 
    ON y.content_id = x.content_id 
    AND 
    (
     (y.user_id = x.user_id AND y.android_id < x.android_id) 
    OR (y.user_id < x.user_id AND y.android_id = x.android_id) 
    ) 
WHERE y.content_id IS NULL; 
+------------+------------+---------+ 
| content_id | android_id | user_id | 
+------------+------------+---------+ 
|   1 |   1 |  1 | 
|   1 |   2 |  2 | 
|   1 |   4 |  3 | 
|   2 |   2 |  1 | 
+------------+------------+---------+ 

あなたが英数字キーを使用して主張した場合、その後、私は複合UNIQUEキーに上記の変換、およびサロゲートを追加することをお勧め代わりにPK。次に、PK上で '<'の比較を行います。

もちろん、 'count'は返される行の数ですが、content_idごとにカウントしたい場合は、SELECTをSELECT content_id, COUNT(*) totalに変更し、最後にGROUP BY content_idを追加してください。

+0

ありがとう@strawberry – user609306

1

このクエリは、与えられたデータをもとに、結果は予想を取得:

select c1.* from 
    (select * from content where content_id = 'a1' group by android_id) c1 
    join 
    (select * from content where content_id = 'a1' group by user_id) c2 
    on 
    c1.android_id = c2.android_id and c1.user_id = c2.user_id; 

これは、MySQLに依存している「機能」は、この問題の説明:あなたがグループを使用して最初の個別の値を返すことができるMySQL Select rows on first occurrence of each unique value、アグリゲーターなし。

+0

(現実が何であれ)マニュアル自体は、この「機能」はもはや存在しないと主張しています。 – Strawberry

+0

これはまだ動作しており、ソーティングはそれほど重要ではないので、安全だと思われます。しかし、@Strawberryはおそらくもっと良い答えを与えているので、おそらくそれを使うのが一番です。 –