2016-07-14 10 views
1

Nachdem ich ein wenig gesucht hatte, dachte ich, dass ich vielleicht eine Lösung gefunden hätte: sql join including null and non existing records. Überqueren Sie Joining meine Tabellen scheint wie ein guter Weg, um mein Problem zu lösen, aber jetzt habe ich einen Haken schlagen:SQL - Beitritt zu nicht existierenden Aufzeichnungen

Im Folgenden werden die Tabellen Ich verwende:

CREATE TABLE [dbo].[DCRSales](
    [WorkingDate] [smalldatetime] NOT NULL, 
    [Store] [int] NOT NULL, 
    [Department] [int] NOT NULL, 
    [NetSales] [money] NOT NULL, 
    [DSID] [int] IDENTITY(1,1) NOT NULL) 

CREATE TABLE [dbo].[Stores](
    [Number] [int] NOT NULL, 
    [Has_Deli] [bit] NOT NULL, 
    [Alcohol_Register] [int] NULL, 
    [Is_Cost_Saver] [bit] NOT NULL, 
    [Store_Status] [nchar](10) NOT NULL, 
    [Supervisor_Number] [int] NOT NULL, 
    [Email_Address] [nchar](20) NOT NULL, 
    [Sales_Area] [int] NULL, 
    [PZ_Store_Number] [int] NULL, 
    [Has_SCO] [bit] NULL, 
    [SCO_Reg] [nchar](25) NULL, 
    [Has_Ace] [bit] NULL, 
    [Ace_Sq_Ft] [int] NULL, 
    [Open_Date] [datetime] NULL, 
    [Specialist] [nchar](2) NULL, 
    [StateID] [int] NOT NULL) 

CREATE TABLE [dbo].[DepartmentMap](
    [Department_Number] [int] NOT NULL, 
    [Description] [nvarchar](max) NOT NULL, 
    [Parent_Department] [int] NOT NULL) 

CREATE TABLE [dbo].[ParentDepartments](
    [Parent_Department] [int] NOT NULL, 
    [Description] [varchar](50) NULL 

DCRSales ist eine Tabelle halten neue und archivierte Daten. Die archivierten Daten sind nicht perfekt, so dass es natürlich bestimmte fehlende Datenlücken gibt und einige Läden, in denen sie eine Abteilung haben, die sie nicht oder nicht mehr haben. Mein Ziel ist es, diese Tabelle mit unserer Abteilungsliste zu verknüpfen, die untergeordneten Abteilungen und übergeordneten Abteilungen aufzulisten und die net-sales für einen bestimmten Zeitraum SUM zu updaten. In Fällen, in denen ein Geschäft in diesem Zeitraum keine Abteilung hat, muss ich es trotzdem als 0,00 anzeigen.

Eine stabilere Lösung wäre wahrscheinlich, nur alle Abteilungen für jedes Geschäft zu speichern, unabhängig davon, ob sie diese Abteilung haben oder nicht (natürlich mit einem Umsatz von 0,00). Aber ich stelle mir vor, dies zu tun und/oder mein Problem hier zu lösen, würde sowieso sehr ähnliche Anfragen erfordern.

Die Abfrage ich versucht habe, ist wie folgt:

WITH CTE AS (
    SELECT S.Number as Store, DepartmentMap.Department_Number as Department, ParentDepartments.Parent_Department as Parent, ParentDepartments.Description as ParentDescription, DepartmentMap.Description as ChildDescription 
    FROM Stores as S CROSS JOIN dbo.DepartmentMap INNER JOIN ParentDepartments ON DepartmentMap.Parent_Department = ParentDepartments.Parent_Department 
    WHERE S.Number IN(<STORES>) AND Department_Number IN(<DEPTS>) 
) 
SELECT CTE.Store, CTE.Department, SUM(ISNULL(DCRSales.NetSales, 0.00)) as Sales, CTE.Parent, CTE.ParentDescription, CTE.ChildDescription 
FROM CTE LEFT JOIN DCRSales ON DCRSales.Department = CTE.Department AND DCRSales.Store = CTE.Store 
WHERE DCRSales.WorkingDate BETWEEN '<FIRSTDAY>' AND '<LASTDAY>' OR DCRSales.WorkingDate IS NULL 
GROUP BY CTE.Store, CTE.Department, CTE.Parent, CTE.ParentDescription, CTE.ChildDescription 
ORDER BY CTE.Store ASC, CTE.Department ASC 

In dieser Abfrage Ich versuche, aus der Shops Tabelle zu einem Geschäft JOIN jede Abteilung an den CROSS, so dass ich eine Kombination von jedem Geschäft zu erhalten und jeder Abteilung . Ich schließe auch die Elternabteilungen jeder Abteilung mit der Beschreibung der Kinderabteilung und der Beschreibung der Elternabteilung ein. Ich filter diesen ersten Teil basierend auf Filiale und Abteilung, aber dies ändert nicht das allgemeine Konzept.

Mit dieser Ergebnismenge versuche ich dann, diese Tabelle mit allen Verkäufen in DCRSales zu verbinden, die innerhalb eines bestimmten Datumsbereichs liegen. Ich füge auch das Datum hinzu, wenn es Null ist, weil die Ergebnisse, die einen NULL-Verkauf haben, auch ein NULL-WorkingDate haben.

Diese Abfrage schien zu funktionieren, bis ich bemerkte, dass nicht alle Abteilungen mit allen Geschäften verwendet werden. Insbesondere die Filialen, die nicht mit allen Abteilungen kombiniert werden, haben keine Daten für den angegebenen Zeitraum (dh sie sind geschlossen). Wenn für die Abteilung keine Daten vorhanden sind, sollten sie dennoch mit der Abteilungsnummer, der übergeordneten Nummer, der Abteilungsbeschreibung und der übergeordneten Beschreibung aufgeführt werden (mit Umsatz als 0,00). Jede Hilfe wird sehr geschätzt.

+0

Ich sehe das Problem nicht, ist Ihre 'cte' nicht die umfassende Liste der Geschäfte/Abteilungen, die Sie suchen? Weil die Abfrage solide aussieht. –

+0

Die Stores, die in der Stores-Tabelle enthalten sind, sind alle vorhanden und ziehen sie alle korrekt zurück. Stores, die keine Daten für den angegebenen Datumsbereich haben, haben jedoch eine zufällige Auswahl der Abteilungen mit $ 0,00. Ich dachte, die Abfrage war auch ziemlich solide, bis ich diese kleine Kuriosität bemerkte. – AlmondMan

+2

Oh, deine 'WHERE'-Klausel filtert sie aus, verschiebe 'DCRSales.WorkingDate BETWEEN' 'UND' '' an deine Join-Kriterien und befreie 'WHERE' –

Antwort

2

Ihre WHERE -Klausel filtert Datensätze aus, die zu einem bestimmten Zeitpunkt einen Umsatz haben, aber nicht für den gewünschten Zeitraum, diese Datensätze erfüllen keines der Kriterien und werden daher ausgeschlossen.

Ich könnte unter denk es sein, aber vielleicht müssen nur bewegen:

DCRSales.WorkingDate BETWEEN '<FIRSTDAY>' AND '<LASTDAY>' 

Um Ihre LEFT JOIN Kriterien und WHERE Klausel loszuwerden. Wenn das nicht stimmt, können Sie den Umsatz nach Datum in einer zweiten CTE vor dem Beitritt filtern.

+0

Das hat definitiv funktioniert! Vielen Dank für die Hilfe. – AlmondMan

0

Was Sie wollen, ist ein OUTER JOIN. diese

Siehe: https://technet.microsoft.com/en-us/library/ms187518(v=sql.105).aspx

+0

Ja, ein Links- oder Rechts-Outer-Join wäre wichtig beim Extrahieren von Datensätzen, die kein Gegenstück in einer anderen Tabelle haben, aber * (in Bezug auf meine oben angebotene Antwort) * Ich denke, dass in dieser tatsächlichen Situation die OP wird feststellen, dass "danach noch viel mehr getan werden muss". –

+1

Bei weiterer Überprüfung sind LEFT JOIN und LEFT OUTER JOIN dasselbe, von denen ich die erste bereits in der erwähnten Abfrage verwende. Ein FULL OUTER JOIN erzeugt auch nicht die richtigen Ergebnisse. Ein RECHTER JOIN wird meines Wissens nur die entsprechenden Geschäfte einschließen. Ich weiß bereits, dass jedes Geschäft in DCRSales mit einem der Abteilungen von CTE abgeglichen wird, was bedeutet, dass es im Wesentlichen das gleiche wie INNER JOIN'ing der beiden wäre. – AlmondMan

0

Ich schlage vor, dass dieser Prozess wahrscheinlich viel zu kompliziert ist, eine einzelne Abfrage zu tun verwenden. Ich denke, dass Sie mehrere Abfragen ausführen müssen: um die Transaktionen von Interesse in eine separate Tabelle zu extrahieren, dann die Ergebnisse ein- oder mehrmals in dieser Tabelle zu ändern, bevor Sie es verwenden, um Ihre endgültigen Statistiken zu erstellen. Eine gespeicherte Prozedur, die mehrere separat gespeicherte Abfragen steuert, könnte verwendet werden, um den Prozess zu steuern, der in mehreren "Stufen" mehrere "Durchläufe" über die anfänglich extrahierten Daten durchführt.

Eine wichtige Information wäre zum Beispiel zu wissen, wenn ein bestimmtes Geschäft eine bestimmte Abteilung hatte. (Zum Beispiel: store, department, starting_date, ending_date.) Dies wäre eine Verfeinerung einer möglicherweise vorhandenen Tabelle (und vielleicht daraus gezogen ...), die auflistet, welche Abteilungen ein bestimmtes Geschäft heute hat.

Lassen Sie uns hoffen, dass abteilungs Zahlen nicht ändern, oder dass Ihr Unternehmen andere Unternehmen nicht mit der daraus resultierenden Notwendigkeit erworben zu „re-map“ diese Zahlen in gewisser Weise.

auch: ehrlich gesagt, wenn Sie Zugang zu einem wirklich guten-Statistiken Paket haben, wie SAS® oder SPSS® ... kann „R“ tun, um diese Art der Sache? ... Sie könnten sich besser fühlen. (Und nein, ich meine nicht „Microsoft Excel ...“) ;-)

Wenn ich mit Anforderungen wie diese konfrontiert wurde (und ich habe schon viele Male ...), ein Statistikpaket war unverzichtbar. Ich fand heraus, dass ich den Prozess und die extrahierten Daten einige Male "massieren" musste, in einem System der sukzessiven Verfeinerung, das mich Schritt für Schritt zu einem Berichtsprozess führte, dem ich vertrauen und daher verteidigen konnte.

+0

Dies ist definitiv eine interessante Lösung. Allerdings verwenden wir kein Statistik-Paket (obwohl ich versuche, sie davon zu überzeugen, R für datenorientierteres Zeug zu verwenden), höhere Leute wollen es JETZT, und ich hatte Glück, die Daten, die sie hatten, einfach in ihre aktuelle Version zu übertragen Format. Wo ich arbeite, wird diesen Dingen leider nicht viel Zeit und Zeit gewidmet. – AlmondMan

+0

Vielleicht können Sie dann eine gespeicherte Prozedur oder ein kurzes Programm/Skript verwenden, um den Prozess ausreichend zu emulieren. Grundsätzlich: um in temporäre Tabellen zu extrahieren, um diese Tabellen auf eine Reihe von Wegen * zu manipulieren (ohne die ursprünglichen Daten zu beeinflussen), * und um die endgültigen Ergebnisse daraus zu erzeugen. Viel Glück. –

Verwandte Themen