Fehlermeldung beim Verarbeiten mehrerer Datensätze

IchHH

SQL-Guru
Beiträge
205
Hallo alle zusammen,

hat jemand eine Idee wie ich den nachfolgenden Code auf ein paar Tausend Datensätze anwenden kann und nicht nur auf einen stark Selectierten Datensatz von ca. 10 Einträgen?

Code:
SELECT --z.proj_group,
    z.v_id,
  Convert(varchar(12),MIN(z.[pbVers_gültig_von]),104) AS [pbVers_gültig_von],
  Convert(varchar(12),dateadd(day,-1,MAX(z.[pbVers_gültig_bis])),104) AS [pbVers_gültig_bis]
FROM (
  SELECT x.v_id, x.[pbVers_gültig_von], x.[pbVers_gültig_bis], (

    SELECT SUM(y.flag)
    FROM (

    SELECT a.*,
      CASE WHEN (SELECT b.v_id FROM #tmp b WHERE a.[pbVers_gültig_von] = b.[pbVers_gültig_bis])
      IS NOT NULL THEN 0 ELSE 1 END AS flag
      FROM #tmp a

    ) y
    WHERE y.v_id <= x.v_id) AS proj_group

  FROM #tmp x
) z
GROUP BY z.proj_group, z.v_id

Danke für eure Hilfe.
 
Werbung:

IchHH

SQL-Guru
Beiträge
205
Die lautet wie Folgt:

Meldung 512, Ebene 16, Status 1, Zeile 20
Die Unterabfrage hat mehr als einen Wert zurückgegeben. Das ist nicht zulässig, wenn die Unterabfrage auf =, !=, <, <=, > oder >= folgt oder als Ausdruck verwendet wird.
 

akretschmer

Datenbank-Guru
Beiträge
9.612
*vermutlich* liefert

Code:
SELECT a.*,
CASE WHEN (SELECT b.v_id FROM #tmp b WHERE a.[pbVers_gültig_von] = b.[pbVers_gültig_bis])
IS NOT NULL THEN 0 ELSE 1 END AS flag
FROM #tmp a

) y
WHERE y.v_id <= x.v_id

bzw. das innere Select da ab und an mehr als eine Zeile, aber - to be honest, wilde Vermutung. Vielleicht sieht @ukulele den Fehler besser ...
 

ukulele

Datenbank-Guru
Beiträge
4.690
Ist schon richtig das ist die einzige Mögliche Stelle, der Code wirkt auch irgendwie schräg, sehr wild verschachtelt und der Subselect mit sum() wird ja immer wieder ausgeführt, pro Zeile einmal. Das wird alles sehr viel Performance kosten.

Kannst du mal ein paar Beispieldaten zeigen und sagen was du erreichen willst?
 

IchHH

SQL-Guru
Beiträge
205
Hallo,

ich versuche gerne das einmal Bildlich darzustellen was ich eigentlich versuche:

Das ist eine Beispielausgangsdatenbank (natürlich mit sehr viel weniger Daten als ich habe)
Code:
+---------+------------+------------+
| v_id | [pbVers_gültig_von] | [pbVers_gültig_bis]   |
+---------+------------+------------+
|       1 | 2010-01-01 | 2010-01-02 |
|       2 | 2010-01-02 | 2010-01-06 |
|       3 | 2010-01-06 | 2010-01-10 |
|       4 | 2010-01-10 | 2010-01-15 |
|       5 | 2010-01-18 | 2010-01-20 |
|       6 | 2010-01-20 | 2010-01-23 |
|       7 | 2010-01-23 | 2010-01-24 |
|       8 | 2010-01-24 | 2010-01-27 |
|       9 | 2010-01-27 | 2010-02-02 |
|      10 | 2010-02-03 | 2010-02-07 |
|      11 | 2010-02-07 | 2010-02-08 |
|      12 | 2010-02-12 | 2010-02-14 |
|      13 | 2010-02-14 | 2010-02-15 |
|      14 | 2010-02-15 | 2010-02-22 |
+---------+------------+------------+

Im Subquery mit der Case Funktion hinterlege ich die Information das ein Flag erzeugt wenn die Zeiträume zusammenhängend sind:
Code:
+---------+------------+------------+------+
| v_id | [pbVers_gültig_von]| [pbVers_gültig_bis]| flag |
+---------+------------+------------+------+
|       1 | 2010-01-01 | 2010-01-02 |    1 |
|       2 | 2010-01-02 | 2010-01-06 |    0 |
|       3 | 2010-01-06 | 2010-01-10 |    0 |
|       4 | 2010-01-10 | 2010-01-15 |    0 |
|       5 | 2010-01-18 | 2010-01-20 |    1 |
|       6 | 2010-01-20 | 2010-01-23 |    0 |
|       7 | 2010-01-23 | 2010-01-24 |    0 |
|       8 | 2010-01-24 | 2010-01-27 |    0 |
|       9 | 2010-01-27 | 2010-02-02 |    0 |
|      10 | 2010-02-03 | 2010-02-07 |    1 |
|      11 | 2010-02-07 | 2010-02-08 |    0 |
|      12 | 2010-02-12 | 2010-02-14 |    1 |
|      13 | 2010-02-14 | 2010-02-15 |    0 |
|      14 | 2010-02-15 | 2010-02-22 |    0 |
+---------+------------+------------+------+

Im nächsten Subquery sorge ich für die Aufsummierung der proj_group um eine eindeutige ID zu erhalten:

Code:
+---------+------------+------------+------------+
| v_id | [pbVers_gültig_von]| [pbVers_gültig_bis]| proj_group |
+---------+------------+------------+------------+
|       1 | 2010-01-01 | 2010-01-02 |          1 |
|       2 | 2010-01-02 | 2010-01-06 |          1 |
|       3 | 2010-01-06 | 2010-01-10 |          1 |
|       4 | 2010-01-10 | 2010-01-15 |          1 |
|       5 | 2010-01-18 | 2010-01-20 |          2 |
|       6 | 2010-01-20 | 2010-01-23 |          2 |
|       7 | 2010-01-23 | 2010-01-24 |          2 |
|       8 | 2010-01-24 | 2010-01-27 |          2 |
|       9 | 2010-01-27 | 2010-02-02 |          2 |
|      10 | 2010-02-03 | 2010-02-07 |          3 |
|      11 | 2010-02-07 | 2010-02-08 |          3 |
|      12 | 2010-02-12 | 2010-02-14 |          4 |
|      13 | 2010-02-14 | 2010-02-15 |          4 |
|      14 | 2010-02-15 | 2010-02-22 |          4 |
+---------+------------+------------+------------+

Zum Schluss lass ich mir nur noch den Minimum und den Maximum Wert anzeigen.

So mein Plan. Das funktioniert ja auch mit nur maximal 24 Datensätzen, darüber hinaus bekomme ich nur Fehlermeldungen.
 
Werbung:

ukulele

Datenbank-Guru
Beiträge
4.690
Also da sollte man auf jedenfall die Macht einsetzen in Form von Window-Funktionen. Ich glaube man muss auch mit Rekursion arbeiten, anders habe ich es jetzt beim expirimentieren nicht hinbekommen, aber damit funktioniert es mit den Testdaten:
Code:
WITH 
t(v_id,start,[pbVers_gültig_von],[pbVers_gültig_bis]) AS (
   SELECT   t1.v_id,
       t1.[pbVers_gültig_von],
       t1.[pbVers_gültig_von],
       t1.[pbVers_gültig_bis]
   FROM   tabelle t1
   LEFT JOIN tabelle t2
   ON     t1.[pbVers_gültig_von] = t2.[pbVers_gültig_bis]
   WHERE   t2.[pbVers_gültig_bis] IS NULL
   UNION ALL
   SELECT   t3.v_id,
       t.start,
       t3.[pbVers_gültig_von],
       t3.[pbVers_gültig_bis]
   FROM   t
   INNER JOIN tabelle t3
   ON     t.[pbVers_gültig_bis] = t3.[pbVers_gültig_von]
   )
SELECT   t.v_id,
     t.[pbVers_gültig_von],
     t.[pbVers_gültig_bis],
     DENSE_RANK() OVER (ORDER BY start) AS proj_group
FROM   t
ORDER BY t.v_id
 
Oben