2016-08-04 8 views
1

Ich habe eine Union von zwei Tabellen und ich zähle die Anzahl der Zeilen in der Union. Ich muss das mehrmals machen, wobei einer der beiden Tische gleich bleibt, aber der andere sich ändert.Erstellen einer Schleife mit einer Union von zwei Tabellen, von denen eine nicht ändert

Um genauer zu sein, nehmen Sie die Mock Abfrage unten als ein Beispiel, die erste Tabelle (über UNION) bleibt unverändert, aber die Bedingung in der 2. Tabelle wird für jede Iteration der Schleife, die ich gerne haben würde. Zum Beispiel e.YearsOfEmployment > 1 AND e.YearsOfEmployment <= 2 für die nächste Iteration der Schleife und e.YearsOfEmployment > 2 AND e.YearsOfEmployment <= 3 für die nächste.

Ich frage mich, ob eine Schleife für das, was ich tun möchte, möglich ist. Wenn es so ist, würde jeder Ratschlag, wie man es konstruiert, sehr geschätzt. Entscheidend ist, ob es möglich ist, die Schleife so zu konstruieren, dass die erste Tabelle nicht für jede Iteration abgefragt werden muss, da sie gleich bleibt.

SELECT COUNT(*) 
    FROM (
     SELECT e.EmployeeID 
      FROM HumanResources.Employee AS e 
      JOIN Sales.SalesPerson AS s 
       ON e.FullName = s.FullName 

     UNION 

     SELECT e.EmployeeID 
      FROM HumanResources.Employee AS e 
     WHERE e.YearsOfEmployment > 0 AND e.YearsOfEmployment <= 1 
     ) AS temp 

EDIT: Hier ist eine Beschreibung dessen, was ich zu erreichen versuche: Ich für die Anzahl der Einzelstücke aussehen wollen, dass (mindestens) eines der beiden Kriterien erfüllen. Das erste Kriterium ändert sich nicht (wie in der ersten Tabelle), und das zweite Kriterium ist, ob ein Element innerhalb eines Bereichs punktet. Der gesamte Bereich von Scores ist 0 - 100, und ich würde gerne Elemente zwischen jedem 5-Punkt-Inkrement finden, zB zwischen 0 und 5, zwischen 5 und 10 und zwischen 10 und 15 ... also das Ergebnis, das ich möchte zu erreichen, ist so etwas wie unten:

# of items fulfilling criterion 1 or score between 0 and 5 
# of items fulfilling criterion 1 or score between 5 and 10 
# of items fulfilling criterion 1 or score between 10 and 15 
# of items fulfilling criterion 1 or score between 15 and 20 
. 
. 
. 
# of items fulfilling criterion 1 or score between 95 and 100 
+0

"Erstellen Sie eine Schleife" ist nur * sehr sehr selten * die richtige Lösung für ein SQL-Problem. Können Sie bitte einen Schritt zurücktreten und Ihr Problem erklären? Es ist fast sicher eine Set-basierte Lösung. – Blorgbeard

+0

Bitte geben Sie Beispieldaten und erwartete Ergebnisse an. Sollte keine Schleifen verwenden müssen btw ... – sgeddes

+0

Überschneiden sich Ihre Kriterien absichtlich? jemand mit 5 Punkten wird in zwei Gruppen gezählt. Wenn sie sich nicht überlappen sollen, können Sie eine GROUP BY verwenden, um zu bekommen, was Sie wollen. Keine Schleifen. Lassen Sie SQL Server nur sorgen, wenn Sie Ihre feste Tabelle zwischenspeichern. –

Antwort

0

eine klassische Art und Weise zu „schaffen“ eine Schleife SQL ist ein table of numbers zu verwenden. Es ist einfach eine Tabelle mit Zahlen von 1 bis einige ausreichend groß. Wenn Sie 20 Mal eine Schleife ausführen müssen, wählen Sie 20 Zeilen aus einer Zahlentabelle aus.

In der Abfrage unten erzeuge ich eine Tabelle von 1000 Zahlen im laufenden Betrieb und wählen Sie 20 Zeilen davon (CTE_Numbers). In der Produktion verwende ich eine permanente Tabelle mit 100K Zeilen.

Für jede Zeile in CTE_Numbers Ich führe Ihre Abfrage mit CROSS APPLY, die die Nummer der aktuellen Zeile in die Logik der Abfrage übergeben können.

WITH 
e1 AS 
(
    SELECT N 
    FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS T(N) 
) -- 10 
,e2 AS 
(
    SELECT 1 AS N FROM e1 AS a CROSS JOIN e1 AS b 
) -- 10*10 
,e3 AS 
(
    SELECT 1 AS N FROM e1 CROSS JOIN e2 
) -- 10*100 
,CTE_Numbers 
AS 
(
    SELECT TOP(20) 
     ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS Number 
    FROM e3 
    ORDER BY Number 
) 
SELECT 
    CTE_Numbers.Number 
    ,CA.cc 
FROM 
    CTE_Numbers 
    CROSS APPLY 
    (
     SELECT COUNT(*) AS cc 
     FROM 
      (
       SELECT e.EmployeeID 
       FROM 
        HumanResources.Employee AS e 
        INNER JOIN Sales.SalesPerson AS s ON e.FullName = s.FullName 

       UNION 

       SELECT e.EmployeeID 
       FROM 
        HumanResources.Employee AS e 
       WHERE 
        e.YearsOfEmployment > CTE_Numbers.Number - 1 
        AND e.YearsOfEmployment <= CTE_Numbers.Number 
      ) AS Temp 
    ) AS CA 
ORDER BY Number; 
1

Diese Abfrage ordnet die Jahre in 5 Jahre Eimer - es laufen und

SELECT e.EmployeeID, (e.YearsOfEmployment -1)/5 as yeargroup 
     FROM HumanResources.Employee AS e 

Diese Abfrage zählt, wie viele in jedem Eimer sind:

SELECT (e.YearsOfEmployment -1)/5 as yeargroup, COUNT(*) 
     FROM HumanResources.Employee AS e 
    GROUP BY (e.YearsOfEmployment -1)/5 

und diese Abfrage klebt es alle zusammen:

SELECT yeargroup, COUNT(*) EmployeeCount 
FROM (
    -- first get the unique list of employees - they might be in both tables 
    -- so we need UNION not UNION ALL 
    SELECT e.employeeid, 
    (e.YearsOfEmployment -1)/5 as yeargroup 
     FROM HumanResources.Employee AS e 
     JOIN Sales.SalesPerson AS s 
      ON e.FullName = s.FullName 

    UNION 

    SELECT e.employeeid, 
    (e.YearsOfEmployment -1)/5 as yeargroup 
     FROM HumanResources.Employee AS e 
    ) AS temp 
GROUP BY yeargroup 
+0

Re: Q1 - Ja, die gleichen Mitarbeiter können definitiv in beiden Tabellen sein. Re: Q2 - EmployeeIDs sind in beiden Tabellen eindeutig - das heißt, in Tabelle 1 gibt es keine doppelte ID und in Tabelle 2 sind auch keine doppelten IDs vorhanden. – Alex

+0

OK dann .... versuchen Sie die Abfrage und sehen Sie, ob es Ihnen ungefähr die Antwort gibt, die Sie wollen. Auch heißer Tipp: Verwenden Sie nicht "UNION", wenn Sie "UNION ALL" verwenden sollten –

+0

Nur eine Frage über "UNION ALL" vs. "UNION", Tabelle 1 und Tabelle 2 haben überlappende MitarbeiterIDs, aber ich möchte nur zählen die eindeutigen IDs - das heißt, wenn in beiden Tabellen eine Mitarbeiter-ID '123456' vorkommt, möchte ich sie nur einmal zählen, sollte ich stattdessen' UNION' verwenden? – Alex

Verwandte Themen