Wie bekomme ich eine Gruppe, bei der die Anzahl Null ist?


12

Ich werde versuchen, aus den Daten meiner SQL Server-Datenbank ein Diagramm zu erstellen. Ich werde alle Straßen mit der Anzahl der Benutzer haben, die in dieser Straße leben, auch wenn die Anzahl Null ist.

Dafür habe ich diese Abfrage versucht:

Create table Streets(
  ID int IDENTITY  primary key,
  Name varchar(100)
);

create table users(
  ID int IDENTITY  primary key,
  Username varchar(100),
  StreetID int references Streets(id)
);

insert into streets values ('1st street'), ('2nd street'), ('3rd street'), 
                           ('4th street'), ('5th street');
insert into users values ('Pol', 1), ('Doortje', 1), ('Marc', 2), ('Bieke', 2), 
                         ('Paulien', 2), ('Fernand', 2), ('Pascal', 2), ('Boma', 3), 
                         ('Goedele', 3), ('Xavier', 4);

select s.name as street, count(s.name) as count 
from users u inner join streets s on u.streetid = s.id
group by s.name

Und es gibt mir diese Ausgabe:

|   | street     | count |
| - | ---------- | ----- |
| 1 | 1st street | 2     |
| 2 | 2nd street | 5     |
| 3 | 3rd street | 2     |
| 4 | 4th street | 1     |

Das Problem ist, dass die 5. Straße, in der kein Benutzer lebt, nicht im Ergebnis angezeigt wird. Könnte ich das mit SQL Server machen? Hier hast du eine Geige

Update: Wenn ja right join, habe ich folgendes Ergebnis:

|   | street     | count |
| - | ---------- | ----- |
| 1 | 1st street | 2     |
| 2 | 2nd street | 5     |
| 3 | 3rd street | 2     |
| 4 | 4th street | 1     |
| 5 | 5th street | 1     | 

Sehen Sie diese Geige.


4
Da niemand erklärt hat, warum Ihre Abfrage nicht das erwartete Ergebnis zurückgibt: Wenn die Aggregatfunktion NULL ignoriert, müssen Sie eine Spalte aus der inneren Tabelle (Sie haben aus der äußeren Tabelle gezählt) zählen, die bekanntermaßen als NICHT NULL definiert ist (um dies zu können) Unterscheiden Sie zwischen NULL-Werten innerhalb der Daten und NULL-Werten, die vom Outer Join erstellt wurden. Der einfachste Weg ist, die Join-Spalte zu zählen:COUNT(u.streetid)
dnoeth

Weil right joinund right outer joinsind die gleichen Dinge. Ich habe meiner Antwort eine Erklärung hinzugefügt, wie von @ jpmc26 vorgeschlagen.
SqlWorldWide

Antworten:


17

Der Grund, warum Ihre Abfrage nicht wie beabsichtigt funktioniert hat:

Inner Join gibt Ihnen den Schnittpunkt von 2 Tabellen. In Ihrem Fall gab es keinen Eintrag für 5th streetin Ihrer Benutzertabelle, und aus diesem Grund hat join keinen Eintrag dafür erstellt.

Die äußere Verknüpfung (rechts oder links) gibt das Ergebnis der inneren Verknüpfung und zusätzlich alle nicht qualifizierenden Datensätze aus der linken oder rechten Tabelle an, abhängig vom Typ (links oder rechts) der äußeren Verknüpfung.

In diesem Fall habe ich Street links vom Join platziert und den linken äußeren Join verwendet, da Sie alle Straßen (gerade Anzahl ist Null) in Ihrer Ergebnismenge haben möchten.

Ändern Sie Ihre Auswahlabfrage in diese.

SELECT S.Name AS Street,
       Count(U.Username) AS COUNT
FROM Streets S
LEFT OUTER JOIN Users U ON U.Streetid = S.Id
GROUP BY S.Name

Ergebnis Geben Sie hier die Bildbeschreibung ein


1
Für mich war der Wechsel von count (*) zu count (customer.id) - ähnlich wie oben gezeigt - der entscheidende Unterschied. Danke :)
Zeek

9

Dies ist ein möglicher Weg.

select s.name as streets,
       (select count(*)
        from   users
        where  StreetID = s.id) cnt
from   streets s;

3
Wenn Sie dieselbe Tabelle in der select-Klausel erneut auswählen, führt dies zu Leistungsproblemen? (+1)
Saqib

7

Bereinigen von Code für die Arbeit an einer Instanz, bei der zwischen Groß- und Kleinschreibung unterschieden wird ...

CREATE TABLE Streets
(
    ID INT IDENTITY PRIMARY KEY,
    Name VARCHAR(100)
);

CREATE TABLE users
(
    ID INT IDENTITY PRIMARY KEY,
    Username VARCHAR(100),
    StreetID INT
        REFERENCES Streets ( ID )
);

INSERT INTO Streets
VALUES ( '1st street' ),
    ( '2nd street' ),
    ( '3rd street' ),
    ( '4th street' ),
    ( '5th street' );
INSERT INTO users
VALUES ( 'Pol', 1 ),
    ( 'Doortje', 1 ),
    ( 'Marc', 2 ),
    ( 'Bieke', 2 ),
    ( 'Paulien', 2 ),
    ( 'Fernand', 2 ),
    ( 'Pascal', 2 ),
    ( 'Boma', 3 ),
    ( 'Goedele', 3 ),
    ( 'Xavier', 4 );

Wenn Sie COUNTeinen Spaltennamen verwenden, werden die NOT NULLWerte gezählt.

Ich benutze ein RIGHT JOINhier, um Joe Obbish zu beschwichtigen.

SELECT   s.Name AS street, COUNT(u.Username) AS count
FROM     users AS u
RIGHT JOIN Streets AS s
ON u.StreetID = s.ID
GROUP BY s.Name

Ergebnisse:

street      count
1st street  2
2nd street  5
3rd street  2
4th street  1
5th street  0

0
  1. Holen Sie sich die Zählung nach Straßen-ID
  2. Verbinden Sie die Straßen-ID mit der ID von den Straßen
  3. Verwenden Sie Coalsesce, da sich der Nullwert ergibt

Hier ist die kurze Abfrage:

select Name, coalesce( u.ct,0)ct FROM streets s left join (
select StreetID,count(*)ct from users group by StreetID)u on s.ID=u.StreetID

Das ist mit links beitreten
Rakesh
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.