2010-12-13 7 views
4

Ich habe eine Tabelle mit der Bezeichnung TempAllAddresses mit den folgenden Spalten - ID, Address, State. Ich möchte eine neue Tabelle mit Address, State und Count füllen. Count sollte darstellen, wie viele Datensätze in der Tabelle TempAllAddresses vorhanden sind, die eine Adresse wie diese Adresse gefolgt von einem Platzhalter haben. Wenn das keinen Sinn, hier ein Beispiel zu veranschaulichen - Lasst uns sagen, dass ich einen Rekord wie dieses:Was ist falsch mit dieser Verbindung einer Tabelle zu sich selbst?

ID  Address  State 
12345 13 Phoenix NY 

Was soll ich tun, um einen neuen Datensatz in eine neue Tabelle einfügen genannt AddressCount, die 13 Phoenix hat für die Address, NY für die State, und die Anzahl der Datensätze in der Tabelle, die NY als den Staat und eine Adresse LIKE '13 Phoenix% 'für die Count haben.

Ich möchte dies mit einer inneren Verbindung von TempAllAddresses auf sich selbst erreichen. Dies ist, was ich habe versucht, aber es scheint nicht zu erreichen, was ich suche:

SELECT t1.Address, t1.State, COUNT(t2.address) As NumEntities 
FROM TempAllAddresses t1 
INNER JOIN TempAllAddresses t2 
ON t1.state = t2.state 
AND T2.Address LIKE t1.address + '%' 
GROUP BY t1.State, t1.Address 

Der Graf ist auf jeden Fall ab, aber. Es sollte der Ausführung "SELECT COUNT(*) FROM TempAllAddresses WHERE State=thisRecordsState and Address LIKE thisRecordsAddress + '%'" entsprechen. Wie kann ich das erreichen? Was mache ich falsch?

Edit:

Die Zahl scheint in der folgenden Art und Weise zu sein, aus - Wenn ich eine Platte haben, wie ich oben erwähnt, und dann habe ich 2 weitere Datensätze, die auch einen Zustand von NY haben, und dann Adressen von "13 Phoenix Straße" haben und "13 Phoenix Rd", dann möchte ich, wie dies in meinem final Table einen Datensatz erhalten:

13 Phoenix NY 3 

Stattdessen scheine ich zu bekommen:

13 Phoenix NY 9 

Ich bin mir nicht ganz sicher, was hier passiert ... eine Art kartesianisches Produkt? Permutationen ...? Kann das jemand erklären?

Edit 2: Ein weiteres bearbeiten, da ich offenbar falsch verstanden werden (und wirklich brauchen eine Lösung :() ... Hier ist eine Abfrage mit einer korrelierten subselect das erreicht, was ich suche ich. d mögen verbinden die gleiche Sache mit einem inneren tun an sich der Tisch eher als ein subselect.

SELECT Address, State, 
    (SELECT Count(*) 
    FROM TempAllAddresses innerQry 
    WHERE innerQry.address LIKE outerQry.address + '%' 
     AND innerQry.state = outerQry.state) As NumEntities 
FROM TempAllAddresses outerQry 

Grundsätzlich für jeden Datensatz, ich möchte die Anzahl der Datensätze in der Tabelle erhalten, die den gleichen Zustand haben und eine Adresse, die mit dieser Adresse beginnt (oder gleich ist ... Ich möchte diese Adresse als Teil der Zählung angeben).

+0

Wie ist der Countdown? Sollte sich jede Zeile selbst zählen (alle zählen> = 1)? –

+0

sieht es tatsächlich korrekt aus. Wenn Sie nicht zusammenfassen (d. h. Gruppe) ist das Ergebnis, was Sie erwarten (für t2.Adresse)? – lijie

+0

Entschuldigung, ich bin ein wenig unscharf, also bin ich mir nicht sicher, ob ich Ihre Kommentare vollständig verstanden habe ... Ich werde versuchen, die Frage zu aktualisieren, um zu erklären, wie die Zählung aus – froadie

Antwort

0

Versuchen Sie stattdessen:

SELECT Orig_Address, State, COUNT(Similar_Address) 
From 
(
    SELECT t1.Address Orig_Address, 
     t1.State State, 
     t2.address Similar_Address 
    FROM TempAllAddresses t1 
    INNER JOIN TempAllAddresses t2 
     ON t1.state = t2.state 
    AND T2.Address LIKE t1.address + '%' 
    AND t1.address <> t2.address 
) 
GROUP BY State, Orig_Address 

EDIT: vergessen haben, den Unterschied zwischen t1.address und t2.address aufzunehmen, wie @Spiny Norman sagte, da Sie wahrscheinlich eine Adresse selbst zu vergleichen, nicht wollen.

HTH

+0

und wie unterscheidet sich das von Gruppierung von t1.address in erster Linie ?? – lijie

+0

Das gibt mir genau die gleichen Ergebnisse, und die Zählung ist immer noch aus ... – froadie

+0

@lijie, Entschuldigung, Sie haben Recht. Ich schrieb das zuerst, erkannte dann, dass es falsch war und wollte nur meinen ausgewählten Vorschlag machen, aber vergessen, diesen Teil des Textes zu löschen. Ich werde es entsprechend bearbeiten. –

0

EDIT: [Ausschnitt old stuff]

Try this:

SELECT t1.Address, t1.State, COUNT(distinct t2.id) As NumEntities 
FROM TempAllAddresses t1 
INNER JOIN TempAllAddresses t2 
ON t1.state = t2.state 
AND T2.Address LIKE t1.address + '%' 
GROUP BY t1.State, t1.Address 
+0

Versuchen Sie Ihren ersten Vorschlag, ich bekomme 0 für NumEntities für alle Zeilen ... Ich würde annehmen, das ist, weil t1.Address <> t1.Address immer falsch ist. Gibt es hier irgendwo einen Tippfehler? – froadie

+0

Yep :) Ich meine t1.Address <> t2.Adresse. Bearbeitet. (Übrigens denke ich, dass die '_%' Lösung eleganter ist, wenn Ihr Datenbankserver dies unterstützt). –

+0

Das scheint mir nicht die richtigen Ergebnisse zu geben ... Ich überprüfe einige zufällige Ergebnisse und sie sind völlig aus, aber nicht in einem erkennbaren Muster. Vielleicht hat es etwas mit dem linken Join zu tun? Ich bin nicht ganz sicher, warum Sie denken, dass dies eine Lösung für das Problem ist, so kann ich nicht wirklich herausfinden, wie man es zwickt ... – froadie

0

QUERY A:

SELECT t1.Address, t1.State, COUNT(t2.address) As NumEntities 
FROM TempAllAddresses t1 
INNER JOIN TempAllAddresses t2 
ON t1.state = t2.state 
AND T2.Address LIKE t1.address + '%' 
GROUP BY t1.State, t1.Address 

ist nicht gleichbedeutend mit

QUERY B :

SELECT Address, State, 
    (SELECT Count(*) 
    FROM TempAllAddresses innerQry 
    WHERE innerQry.address LIKE outerQry.address + '%' 
     AND innerQry.state = outerQry.state) As NumEntities 
FROM TempAllAddresses outerQry 

weil B für jede Zeile in der ursprünglichen Tabelle 1 Zeile erzeugt (TempAllAddresses), wohingegen ein Willen Gruppe zusammen Zeilen in der ursprünglichen Tabelle, die den gleichen Zustand und Adresse hat. Um dies zu lösen, GROUP BY t1.ID, t1.State, t1.Address stattdessen.

+0

@lijie stimmte zu, aber ich glaube nicht, dass sogar die Subselect-Version wirklich das tut, was froadie will, trotz dem, was er sagt - ich denke, es ist wahrscheinlicher, er will 1 Reihe für jede einzelne Adresse, Zustand –

+0

@jackpdouglas: Ja, würde ich das denken das ist die eigentliche Absicht (aber das tut immer noch Gedankenlesen, bis OP bestätigt). zu diesem Zweck würde es genügen, 'DISTINCT' nach dem Schlüsselwort' SELECT' hinzuzufügen (ich habe nicht genug Erfahrung, um das zu wissen, aber das würde ich natürlich versuchen, wenn ich keine Unterabfragen hätte). – lijie

+0

@lijie, das würde die "richtige" Anzahl von Zeilen bekommen, aber die "Anzahl" würde nicht funktionieren - siehe meine Antwort für das, was ich stattdessen tun würde –

0

Es wird doppelt gezählt, wenn mehrere Zeilen mit genau der gleichen Adresse vorhanden sind.

Versuchen:

SELECT t1.Address, t1.State, COUNT(t2.address) As NumEntities 
FROM (select distinct Address, State from TempAllAddresses) t1 
INNER JOIN TempAllAddresses t2 
ON t1.state = t2.state 
AND T2.Address LIKE t1.address + '%' 
GROUP BY t1.State, t1.Address 
0

Nested GroupBy:

  • Die Unterabfrage wird die kürzeste Adresse für jede einzelne Adresse finden.
  • Dies berücksichtigt nicht die Groß-/Kleinschreibung.
  • Dann wird jede Version dieser Adressen gezählt.

SQL:

SELECT Address, State, count(1) As NumEntities 
FROM ( 
    SELECT min(t1.Address) as Address, t1.State 
    FROM TempAllAddresses t1 
    INNER JOIN TempAllAddresses t2 
    ON t1.state = t2.state 
    AND T2.Address LIKE t1.address + '%' 
    GROUP BY t1.State, t2.Address 
) GROUP By State, Address 
0

Haben Sie analytische Funktionen ausprobiert - sie sind oft die einfachste Lösung. Ich bin nicht vertraut mit Tabellenstruktur, aber es sollte wie folgt sein:

SELECT t1.Address, t1.State, 
COUNT(t2.address) OVER (PARTITION BY t2.state) As NumEntities 
FROM TempAllAddresses t1 
INNER JOIN TempAllAddresses t2 
ON t1.state = t2.state 
AND T2.Address LIKE t1.address + '%' 
GROUP BY t1.State, t1.Address 

Sie sogar ORDER BY in der OVER Klausel hinzufügen können. Eine Erläuterung finden Sie unter Oracle FAQs.

+0

I haven ' t arbeitete mit Oracle vor Also kann ich nicht sagen, ob das funktionieren wird, aber in SQL Server ist das ungültig, weil t2.address und t2.state nicht in der GROUP BY-Klausel enthalten sind. –

+0

@ Jeremy: SQL Server ist eine ganz andere Sache. Dieser Teil von SQL ist Oracle-spezifisch. – RapidCoder

+0

Ah ok. Danke für die Klarstellung. –

1

Hier sind zwei Lösungen, eine mit einem Cross APPLY und die andere mit einem INNER JOIN, wie Sie ursprünglich wollten. Ich hoffe das hilft. :)

DECLARE @TempAllAddresses TABLE 
(
    ID INT PRIMARY KEY IDENTITY(1, 1) NOT NULL 
    , [Address] VARCHAR(250) NOT NULL 
    , [State] CHAR(2) NOT NULL 
) 

INSERT INTO @TempAllAddresses 
VALUES ('13 Phoenix', 'NY') 
     , ('13 Phoenix St', 'NY') 
     , ('13 Phoenix Street', 'NY') 
     , ('1845 Test', 'TN') 
     , ('1337 Street', 'WA') 
     , ('1845 T', 'TN') 

SELECT 
    TempAddresses.ID 
    , TempAddresses.[Address] 
    , TempAddresses.[State] 
    , TempAddressesCounted.AddressCount 
FROM @TempAllAddresses TempAddresses 
CROSS APPLY 
(
    SELECT 
     COUNT(*) AS AddressCount 
    FROM @TempAllAddresses TempAddressesApply 
    WHERE TempAddressesApply.[Address] LIKE (TempAddresses.[Address] + '%') 
     AND TempAddressesApply.[State] = TempAddresses.[State] 
) TempAddressesCounted 

SELECT 
    TempAddresses.ID 
    , TempAddresses.[Address] 
    , TempAddresses.[State] 
    , COUNT(*) AS AddressCount 
FROM @TempAllAddresses TempAddresses 
INNER JOIN @TempAllAddresses TempAddressesJoin 
    ON TempAddressesJoin.[Address] LIKE (TempAddresses.[Address] + '%') 
      AND TempAddressesJoin.[State] = TempAddresses.[State] 
GROUP BY TempAddresses.ID 
    , TempAddresses.[Address] 
    , TempAddresses.[State]