2016-05-25 12 views
0

wir uns vor, ich habe zwei TabellenErhalten Spiel der Gruppe von Werten

**T1** 
T1ID 
---- 
1 
2 
3 

**T2** 
T2ID| T1ID| VALUE| 
------------------ 
    1| 1|  1| 
    2| 1|  2| 
    3| 2|  1| 
    4| 2|  3| 
    5| 2|  2| 
    6| 3|  1| 
    7| 3|  4| 

T1 eine Gruppierung Wertetabelle in T2 ist Deshalb habe ich drei Gruppen von Werten

1 = 1, 2 
2 = 1, 2, 3 
3 = 1, 4 

Ist es ist möglich, eine Abfrage zu schreiben, um alle Gruppen zu erhalten, die mit der Menge der Werte übereinstimmen?

SELECT … WHERE VALUE IN (1, 2, 3) 
SHOULD GIVE AS RESULT 
1 
2 

SELECT … WHERE VALUE IN (1, 4) 
SHOULD GIVE AS RESULT 
3 

eine der Antworten unter Punkt mich in der richtigen Art und Weise zu graben:

SELECT s.t1id 
    FROM (SELECT t1id, COUNT(value) itemCount 
      FROM t2 
     WHERE VALUE IN (1, 2, 3) -- put set of values here 
     GROUP BY t1id) s 
    JOIN (SELECT t1id, COUNT(VALUE) itemCount 
      FROM t2 
     GROUP BY t1id) j 
    ON s.t1id = j.t1id 
WHERE s.itemCount >= j.itemCount 

Könnte jemand die Abfrage verbessern?

+2

im ersten Beispiel, warum es 1 zurückgeben sollte? – SSD

+0

Hier ist ein großartiger Ort, um zu beginnen. http://spaghettidba.com/2015/04/24/how-to-post-at-sql-question-on-a-public-forum/ Wie dort gepostet gibt es einfach nicht viele Informationen hier und welche Informationen es gibt, ist nicht sehr klar. –

+0

2 Saeid, denn das ist Teilmenge der (1,2,3) Set –

Antwort

0

Ich schrieb die unten ... nicht sicher, ob Sie Oracle verwenden oder nicht, aber das scheint zu funktionieren. Lassen Sie mich wissen, ob dies für Sie effizienter ist.

select * 
from 
(
    select 
    t1_id, 
    LISTAGG(value, '') WITHIN GROUP (ORDER BY value) value_list 
    from 
    (
     select 1 t1_id, 1 value from dual union all 
     select 1 t1_id, 2 value from dual union all 
     select 2 t1_id, 1 value from dual union all 
     select 2 t1_id, 3 value from dual union all 
     select 2 t1_id, 2 value from dual union all 
     select 3 t1_id, 1 value from dual union all 
     select 3 t1_id, 4 value from dual 
    ) 
    t2 
    group by t1_id 
) 
where 
instr('123',value_list) > 0 

EDIT: Ich bemerkte das SQLServer-Tag ... gerade jetzt. Das tut mir leid. Also habe ich meine Lösung in SQLServer-Syntax umgeschrieben.

ZUSÄTZLICHE BEARBEITUNG: Richtig Sie sind ... Ich denke, die unten wird dieses Verhalten korrigieren. Ich kann jedoch die Effizienz des folgenden Ansatzes nicht kommentieren. Ich könnte mir vorstellen, dass die In-Line-Funktion von LISTAGG in Oracle effizienter sein könnte - und sei es nur, weil klügere Leute als ich es optimiert haben.

with t2 as 
(
    select 1 t2_id, 1 t1_id, 1 value union all 
    select 2 t2_id, 1 t1_id, 2 value union all 
    select 3 t2_id, 2 t1_id, 1 value union all 
    select 4 t2_id, 2 t1_id, 3 value union all 
    select 5 t2_id, 2 t1_id, 2 value union all 
    select 6 t2_id, 3 t1_id, 1 value union all 
    select 7 t2_id, 3 t1_id, 4 value 
) 
SELECT 
* 
FROM 
(
    SELECT DISTINCT 
    b.t1_id, 
    STUFF(CAST((
      SELECT [text()] = '' + cast(a.Value AS VARCHAR(100)) 
      FROM t2 a 
      WHERE a.t1_id = b.t1_id 
      ORDER BY a.Value 
      FOR XML PATH(''), TYPE) AS VARCHAR(1000)), 1, 0, '' 
    ) value_list 
    from 
    t2 b 
) x 
where 
CHARINDEX(value_list,'123',1) > 0 OR 
CHARINDEX('123',value_list,1) > 0 

FINAL EDIT: Sorry, ich habe diese in den Kommentaren getan, wenn ich nicht zu neu erachtet wurde, ein Benutzer, Kommentare hinterlassen zu dürfen. Ich denke du hast Recht. Ich habe die Anforderungen nicht vollständig verstanden, aber ich fange an. Wenn wir sagen, dass wir t2 einen Wert (1,3) hinzufügen, wird mein Prozess bei einer Suche nach "123" erneut fehlschlagen. Ich denke, dass meine derzeitige Lösung falsch ist, aber ich denke, dass es einige Vorzüge geben kann, um zu pivotieren und zu sortieren, um einen effizienteren Mustervergleich zu ermöglichen. Konnte den LISTAGG-Teil davon jedoch wahrscheinlich beseitigen. Aber da Sie bereits eine funktionierende Lösung haben, kann es für mich am besten sein, sich von produktiven Problemen zu verabschieden.

Sorry, ich habe nicht geholfen, haha. Viel Glück für Sie, mein Herr.

+0

Vielen Dank Andy. Ich schätze deine Hilfe sehr. Ich habe deine Anfrage getestet. 1. Es hat einen Fehler - stellen wir uns Wert = 23 in t2 Tabelle vor. (Natürlich können wir zwischen Werten in value_list abgegrenzt hinzufügen, um es zu beheben). 2. es hat eine Begrenzung mit der Länge von varchar (1000) - sicher können wir es auch erhöhen. 3. Also die Hauptfrage an Sie: Könnten Sie mir bitte zumindest auf die Information hinweisen, dass diese Art der Abfrage (ich habe die letzten 20 Jahre nie benutzt) schneller ist weniger Belastung | was auch immer als Frage am Ende meiner Frage? –

0

Sie können dies auf verschiedene Arten erreichen. Die Prüfung auf den gegenüberliegenden („nicht in der Liste“) kann zu interessanten Lösungen führen:

SELECT t1id 
FROM  t2 
GROUP BY t1id 
HAVING COUNT(CASE WHEN value NOT IN (1,4) THEN 1 END) = 0 

Die obige Abfrage enthält nicht die Schlüssel für die kein Wert überhaupt in der Tabelle ist t2. Streng genommen ist eine leere Menge eine Untermenge einer anderen Menge, so dass diese Schlüssel auch tatsächlich aufgelistet werden sollten. Mit einer äußeren Verknüpfung dies erreicht werden kann, wie folgt aus:

SELECT t1.t1id 
FROM  t1 
LEFT JOIN t2 
     ON t1.t1id = t2.t1id 
GROUP BY t1.t1id 
HAVING COUNT(CASE WHEN value NOT IN (1,4) THEN 1 END) = 0 

Oder mit dem IN Test als äußere Join-Bedingung:

SELECT t1.t1id 
FROM  t1 
LEFT JOIN t2 
     ON t1.t1id = t2.t1id 
     AND value NOT IN (1,4) 
WHERE  t2.t1id IS NULL 
GROUP BY t1.t1id 

Oder mit einer Unterabfrage:

SELECT t1id 
FROM  t1 
WHERE t1id NOT IN (SELECT t1id 
         FROM t2 
         WHERE value NOT IN (1,4)) 

Sie könnten auch MINUS verwenden, die ganz intuitiv:

SELECT t1id 
FROM  t1 
MINUS 
SELECT t1id 
FROM  t2 
WHERE t1id NOT IN (1,4) 

Testen Sie, was in Ihrem Fall die beste Leistung bringt.

Verwandte Themen