2016-08-08 58 views
1

Ich brauche nur distinct address_id im Ergebnis keine Verdoppelung zu erhalten. Hier ist meine Abfrage.Entfernen Sie doppelte address_id von SQL-Datensatz

SELECT DISTINCT address.address_id, address.address1, address.streetcity, state.stateabbrev, rtrim(ltrim(case when address.streetzipcode is not null and address.streetzipcode != 'NULL' then address.streetzipcode else '' end))+case when len(address.streetzipplus4)>0 then '-'+rtrim(ltrim(address.streetzipplus4)) else '' end as streetzipcode, address.homephone, 
     dbo.f_addressstudent (student.address_id) as Students, 
     dbo.f_addresspeople (student.address_id) as Adults, 
     case 
      when @classif_id IS NULL then 0 
      else 
      student.classif_id 
     end classif, 
     classifctn 
    FROM district WITH(NOLOCK) 
     JOIN dbo.building ON building.district_id = district.district_id 
     JOIN dbo.studbldg_bridge WITH(NOLOCK) ON studbldg_bridge.bldg_id=building.bldg_id 
     JOIN dbo.student WITH(NOLOCK) ON student.student_id = studbldg_bridge.student_id 
     JOIN classif with(nolock) on student.classif_id = classif.classif_id 
     LEFT JOIN dbo.address WITH(NOLOCK) ON student.address_id = address.address_id 
     LEFT JOIN dbo.state WITH(NOLOCK) ON address.streetstate_id = state.state_id 
     LEFT JOIN dbo.state AS mailstate WITH(NOLOCK) ON address.state_id = mailstate.state_id 
    WHERE district.district_id = (SELECT district_id FROM dbo.building WITH(NOLOCK) WHERE bldg_id = @bldg_id) 
    ORDER BY classif,Adults, Students 

Dies ist Ergebnis der Abfrage Query result with error in data

Ich habe versucht Gruppe durch und verwenden Aggregatfunktion mit address_id aber ich habe auch nicht-Aggregat Spalten, so dass es nicht für mich gearbeitet hat. Danach versuchte ich auch mit OVER (Partition von address.address_id), aber es hat auch nicht funktioniert.

Jede Hilfe wird im Voraus geschätzt werden.

Danke

** UPDATE auf Business-Logik/Anforderungen **

I eindeutige Adressen für Eltern von Studenten bekommen müssen. Da Eltern zwei oder mehr Kinder haben können, die in der gleichen Adresse leben, verursacht es Verdoppelung. Ich muss nur ein Kind pro Elternteil mit anderen Worten bekommen.

+1

Wenn es Duplikate, wie soll die Klassifizierung (zum Beispiel) entschlossen? Ohne Ihre Anforderungen vollständig zu definieren, ist es unmöglich, eine "richtige" Antwort zu erhalten. –

+0

Ich habe das mysql-Tag entfernt, denn wenn Sie eine Fensterfunktion OVER (Partition ....) versuchen, bedeutet das, dass Sie sie nicht verwenden, da Fensterfunktionen in mysql nicht existieren. Bitte markieren Sie nur die Rdbms, die Sie tatsächlich verwenden. – Matt

+0

Ich aktualisiere Frage, um Ihnen mehr Informationen über Anforderungen zu geben. – NKhan

Antwort

0

Von Ihrem Bild der Ergebnisse sieht es aus wie die classifctn Spalte mehr als 1 Wert hat, so dass es Ihre Zeile dadurch wiederholt. Um eine eindeutige address_id und den Rest der Spalten zu erhalten, entfernen Sie diese entweder aus Ihrer Abfrage oder Sie können eine Priorität setzen, die nur 1 Datensatz pro address_id zurückgibt. Bitte markieren Sie nur die RDBMs, die Sie tatsächlich verwenden. MySQL zum Beispiel Fensterfunktionen hat noch nicht getaggten es noch referenziert mit OVER (Partition .... die

;WITH cte (
    SELECT DISTINCT address.address_id, address.address1, address.streetcity, state.stateabbrev, rtrim(ltrim(case when address.streetzipcode is not null and address.streetzipcode != 'NULL' then address.streetzipcode else '' end))+case when len(address.streetzipplus4)>0 then '-'+rtrim(ltrim(address.streetzipplus4)) else '' end as streetzipcode, address.homephone, 
      dbo.f_addressstudent (student.address_id) as Students, 
      dbo.f_addresspeople (student.address_id) as Adults, 
      case 
      when @classif_id IS NULL then 0 
      else 
      student.classif_id 
      end classif, 
      classifctn, 

      ROW_NUMBER() OVER (PARTITION BY address.address_id ORDER BY HOW WILL YOU CHOOSE?) AS RowNum 

     FROM district WITH(NOLOCK) 
      JOIN dbo.building ON building.district_id = district.district_id 
      JOIN dbo.studbldg_bridge WITH(NOLOCK) ON studbldg_bridge.bldg_id=building.bldg_id 
      JOIN dbo.student WITH(NOLOCK) ON student.student_id = studbldg_bridge.student_id 
      JOIN classif with(nolock) on student.classif_id = classif.classif_id 
      LEFT JOIN dbo.address WITH(NOLOCK) ON student.address_id = address.address_id 
      LEFT JOIN dbo.state WITH(NOLOCK) ON address.streetstate_id = state.state_id 
      LEFT JOIN dbo.state AS mailstate WITH(NOLOCK) ON address.state_id = mailstate.state_id 
     WHERE district.district_id = (SELECT district_id FROM dbo.building WITH(NOLOCK) WHERE bldg_id = @bldg_id) 
) 

SELECT * 
FROM 
    cte 
WHERE 
    RowNum = 1 
ORDER BY 
    classif 
    ,Adults 
    ,Students 

Alternativ in mysql nicht möglich wäre, könnten Sie nisten Ihre Auswahlabfrage. Note obwohl diese Lösung etwas unbrauchbar, da es nur 1 Grad/classifctn zurückgibt, wenn mehr als 1 in einem Haushalt vorhanden ist, wenn Sie sich wirklich nicht um die Spalte kümmern, dann sollten Sie es nur aus Ihrer Abfrage entfernen.

Eigentlich sowohl Ihre classifctn und classif Spalten Wenn Sie mehr als einen Schüler an der gleichen Adresse haben, werden Sie mehrere Zeilen haben, hier können Sie diese Werte zu einer einzelnen Zeile verketten.Sie sollten mehr Zeit für Ihren Geschäftsfall aufwenden und es für uns definieren. Aber hier ist ein Beispiel für Sie:

SELECT DISTINCT 
    address.address_id 
    ,address.address1 
    ,address.streetcity 
    ,state.stateabbrev 
    ,LTRIM(RTRIM(ISNULL(NULLIF(address.streetzipcode,'NULL'),''))) 
     + CASE WHEN LEN(address.streetzipplus4) > 0 THEN '-' ELSE '' END 
     + LTRIM(RTRIM(ISNULL(address.streetzipplus4,''))) AS streetzipcode 
    ,address.homephone 
    ,dbo.f_addressstudent (student.address_id) as Students 
    ,dbo.f_addresspeople (student.address_id) as Adults 
    , case 
     when @classif_id IS NULL then 0 
     else student.classif_id 
     end classif 

     ,STUFF(
     (SELECT ',' + CAST(classif_id AS VARCHAR(100)) 
     FROM 
      classif c 
     WHERE c.classif = student.classif 
     FOR XML PATH('')) 
     ,1,1,'') AS classifs 

     ,STUFF(
     (SELECT ',' + CAST(classifctn AS VARCHAR(100)) 
     FROM 
      classif c 
     WHERE c.classif = student.classif 
     FOR XML PATH('')) 
     ,1,1,'') AS classifctns 
FROM 
    district WITH(NOLOCK) 
    INNER JOIN dbo.building 
    ON building.district_id = district.district_id 
    AND building.bldg_id = @bldg_id 
    INNER JOIN dbo.student WITH(NOLOCK) 
    ON student.student_id = studbldg_bridge.student_id 
    INNER JOIN dbo.address WITH(NOLOCK) 
    ON student.address_id = address.address_id 
    LEFT JOIN dbo.state WITH(NOLOCK) 
    ON address.streetstate_id = state.state_id 

Hinweis I, wenn vor und änderte die Postleitzahl Logik Ihnen zu zeigen, einige Verwendung von ISNULL() und NULLIF(), die in Fällen wie diese hilfreich sind. Ich habe auch 3 Tabellen entfernt, weil 2 nicht verwendet werden und die dritte wird in einem Subselect verwendet, um die Werte zu verketten. Auch Adresstabelle wurde geändert, um ein INNER JOIN, weil, wenn eine Adresse nicht alle anderen Informationen existieren wird leer/nutzlos ....

INNER JOIN dbo.studbldg_bridge WITH(NOLOCK) ON studbldg_bridge.bldg_id=building.bldg_id  
    LEFT JOIN dbo.state AS mailstate WITH(NOLOCK) ON address.state_id = mailstate.state_id 
    INNER JOIN classif with(nolock) on student.classif_id = classif.classif_id 
+0

Ich brauche diese Informationen im Resultset, kann nicht entfernt werden.Wie kann ich einen Vorrang festlegen? – NKhan

+0

das liegt ganz bei Ihnen, wie werden Sie feststellen, welche classifctn ist die Sie wollen? Wenn Sie sagen, dass Sie beide wollen, dann wollen Sie die Zeilen zu einer einzigen durch Komma getrennten Zeichenfolge verketten? Wenn das erstere verwendet werden könnte, könnten Sie eine Zeilennummer() OVER (Partition von Adresse_ID) verwenden und dann where = 1 von Cte oder geschachtelte Abfrage auswählen. Und im letzteren Fall würde ich entweder einen rekursiven CTE oder XML PATH mit einer Subauswahl verwenden. Beachten Sie, dass Sie die genaue Datenbank markieren müssen, die Sie verwenden, da die Antworten variieren werden. – Matt

+0

Eigentlich habe ich row_number() OVER (order by address_id) versucht. Aber wenn ich in Where-Klausel versucht, auf abc zuzugreifen, gibt es mir Fehler, der sagt "ungültige Spalte" – NKhan