2017-01-14 7 views
0

Ich habe zwei Tabellen (T1/T2):
Wie beitreten zwei Tabellen ohne Wiederholung zwei Spalten in MySQL

 T1       T2 
    id | value     id | value 
    1 | 10     1 | 5 
    2 | 10     2 | 15 
    3 | 5     3 | 15 
    4 | 15     4 | 5 
    5 | 5     5 | 10 

ich wähle T2 Aufzeichnungen basierend auf T1 (wenn T1> = Menge der Datensätze mit der gleicher Wert):

SELECT t.id t2_id, t.value value 
FROM t2 as t 
WHERE 
(SELECT COUNT(*) FROM t1 WHERE t1.value = t.value) >= (SELECT COUNT(*) FROM t2 WHERE t2.value = t.value) 

Wie erwartet, diese Rückkehr:

t2_id | value 
     1 | 5 
     4 | 5 
     5 | 10 

Das Problem ist, wenn ich zu attac bin versucht, h die t1_id Spalte ohne Wiederholung einer ID. Die Reihenfolge spielt keine Rolle. Also im Grunde suche ich nach dieses Ergebnis:

t1_id | t2_id | value 
    3 | 1 | 5 
    5 | 4 | 5 
    1 | 5 | 10 

Jeden Versuch, mit JOIN und Gruppen enden mit den t1_id der ersten Datensatz für jeden Block Wert abgestimmt.

+1

Es ist verwirrend, dass Sie mit 't1_id' in Ihrem Ergebnis - was die Regel ist, für die man schließen, wenn mehr als 1 zur Verfügung steht? – DaveCoast

+0

@DaveCoast t1_id Müssen nur den gleichen Wert mit t2_id teilen, der Rest ist egal, solange die t1_id und t2_id nie mehr als einmal erscheinen. – user3456020

+0

In Ihren Beispieldaten sind Sie nicht an Wert 15 interessiert, weil es 2 in t2 gibt, aber nur 1 in t1 und Sie nur an 1 Wert 10 in t1 interessiert sind, weil es nur 1 Wert 10 in t2 gibt? –

Antwort

0
MariaDB [sandbox]> SELECT T1.ID,T2.ID,T1.VALUE 
    -> FROM 
    -> (
    -> SELECT * FROM 
    -> (
    -> SELECT T2.*,(SELECT COUNT(*) FROM T2 T21 WHERE T21.VALUE = T2.VALUE) T2OBS, 
    -> (SELECT COUNT(*) FROM T1 WHERE T1.VALUE = T2.VALUE) T1OBS, 
    -> IF(T2.VALUE <> @P,@RN:=1,@RN:[email protected]+1) RN, 
    -> @P:=T2.VALUE P 
    -> FROM (SELECT @RN:=0,@P:=0) RN,T2 
    -> ORDER BY T2.VALUE,T2.ID 
    ->) S 
    -> WHERE T1OBS >= T2OBS 
    ->) T2 
    -> JOIN 
    -> (
    -> SELECT T1.*, 
    -> IF(T1.VALUE <> @P,@RN:=1,@RN:[email protected]+1) RN, 
    -> @P:=T1.VALUE P 
    -> FROM (SELECT @RN:=0,@P:=0) RN,T1 
    -> ORDER BY T1.VALUE,T1.ID 
    ->) T1 
    -> ON T1.RN = T2.RN AND T1.VALUE = T2.VALUE 
    -> WHERE T1.RN <= T2.T2OBS 
    -> ORDER BY T1.VALUE,T1.ID; 
+------+------+-------+ 
| ID | ID | VALUE | 
+------+------+-------+ 
| 3 | 1 |  5 | 
| 5 | 4 |  5 | 
| 1 | 5 | 10 | 
+------+------+-------+ 
3 rows in set (0.00 sec) 
+0

Dies ist eine schnelle und elegante Lösung! Genau das, was ich will. Vielen Dank! Genial. – user3456020

0

Das Schlüsselwort DISTINCT wird verwendet, doppelte Zeilen aus einem Abfrageergebnis zu beseitigen:

SELECT DISTINCT ... FROM A JOIN B ON .. 
+0

Möchten Sie Ihre Lösung mit tatsächlichem Code erweitern, der das gewünschte Outcomet erzeugt? –

+0

Ja, aber unterschiedliche Zeilen. Ich versuche, in zwei spezifischen Spalten nie doppelt zu erhalten. d.h. ich kann in diesem kleinen Fall keine [[1,1], [1,2]] - Kombination (die verschiedene Reihen sind), nur [1,1] oder [1,2] akzeptieren. – user3456020

0

Ich bin nicht sicher, ob dies der beste Weg ist.

select t2_s1.id t2_id, t2_s0.value 
    from t2 t2_s0 
    join (
     select t2_s3.id, @rowno1 := if(@blk1 = value, @rowno1 + 1, 1) as id_i, @blk1 := value 
     from (
     select * 
     from t2 order by value, id 
    ) t2_s3 
     cross join (
     select @rowno1 := 0, @blk1 := null) t2_s2 
     order by value 
    ) t2_s1 
    on t2_s0.id = t2_s1.id 
    join( 
     select value, t1_s3.id, @rowno2 := if(@blk2 = value, @rowno2 + 1, 1) as id_i, @blk2:= value 
     from (
      select * from t1 order by value, id) t1_s3 
      cross join (
      select @rowno2 := 0, @blk1 := null 
     ) t1_s2 
     order by value 
    ) t1_s1 
     on t2_s1.id_i = t1_s1.id_i 
     and t2_s0.value= t1_s1.value 
    where 
    (select count(*) from t1 where t1.value= t2_s0.value) >= (select count(*) from t2 where t2.value= t2_s0.value) 

Im Grunde ich eine Autoinkrement-ID bin generatin für jeden Block von Wert in beide Tabellen

╔═══════════════════╗  ╔═══════════════════╗ 
║  T1   ║  ║  T2   ║ 
╠════╦═══════╦══════╣  ╠════╦═══════╦══════╣ 
║ id ║ value ║ id_i ║  ║ id ║ value ║ id_i ║ 
╠════╬═══════╬══════╣  ╠════╬═══════╬══════╣ 
║ 1 ║ 10 ║ 1 ║  ║ 1 ║  5 ║ 1 ║ 
║ 2 ║ 10 ║ 2 ║  ║ 2 ║ 15 ║ 1 ║ 
║ 3 ║  5 ║ 1 ║  ║ 3 ║ 15 ║ 2 ║ 
║ 4 ║ 15 ║ 1 ║  ║ 4 ║  5 ║ 2 ║ 
║ 5 ║  5 ║ 2 ║  ║ 5 ║ 10 ║ 1 ║ 
╚════╩═══════╩══════╝  ╚════╩═══════╩══════╝ 

Mit dem erzeugten ID_i on-the-fly Plus Die Wert Spalte kann ich simulieren uniques IDs für die One to One-Beziehung

SQLFiddle