2016-07-19 3 views
0

Ich habe eine Tabelle 1SQL Server 2012: Verschieben von Spalten auf der Grundlage der Logik

(Payee_ID INT, 
BOX1 VARCHAR(2) NULL, -- possible value only AA 
BOX2 VARCHAR(2) NULL, -- possible value only BB 
BOX3 VARCHAR(2) NULL, -- possible value only CC 
BOX4 VARCHAR(2) NULL) -- possible value only DD 

Tabelle 1 Werte:

1, NULL, ‘BB’, NULL, ‘DD’ 
2, ‘AA’, NULL, NULL, ‘DD’ 
3, NULL, ‘BB’, ‘CC’, ‘DD’ 
4, ‘AA’, ‘BB’, NULL, ‘DD’ 
5, ‘AA’, ‘BB’, ‘CC’, ‘DD’ and so on.. 

ich eine andere table2 erstellt haben

(Payee_ID INT, 
BOX1 VARCHAR(2), --AA 
BOX2 VARCHAR(2), --BB 
BOX3 VARCHAR(2), --CC 
BOX4 VARCHAR(2)) --DD 

nun diese Tabelle füllen Verwenden Sie Table1, aber die Regel ist, wenn Box1 null ist, dann Box2's Wert für Box1 und so weiter verwenden. So ist die erwartete Ausgabe ist:

Payee_ID  Box1 Box2 Box3 Box4 
1,    ‘BB’, ‘DD’, ’’ ,  ’’ 
2,    ‘AA’, ‘DD’, ’’ ,  ’’ 
3,    ‘BB’, ‘CC’, ‘DD’, ‘’ 
4,    ‘AA’, ‘BB’, ‘DD’, ‘’ 
5,    ‘AA’, ‘BB’, ‘CC’, ‘DD’ 
+3

Das klingt wie etwas, sollten Sie in der Präsentationsschicht und nicht in der Datenbank –

+0

Für Payee_ID 1 Warum ist box4 leer tun? Sollte es nicht DD sein? und würde Box3 nicht DD sein? – scsimon

+0

@scsimon: Nein, das ist die Voraussetzung. Wenn die vorherigen Felder leer sind, verschieben Sie die Daten aus den Spalten, in denen Daten enthalten sind. Also, für payee1, da box1 ist null und box2 ist BB, BB wird in box1 und so weiter verschoben. – user3294322

Antwort

0

Check this out ... obwohl ich glaube, noch sollten Sie dies nicht tun, in der DB

IF OBJECT_ID('tempdb..#thisTest') IS NOT NULL DROP TABLE #thisTest 

SELECT 
1 as ID, NULL as BOX1, 'BB' as BOX2, NULL as BOX3, 'DD' as BOX4 
INTO #thisTest 
UNION ALL 
SELECT 
2, 'AA', NULL, NULL, 'DD' 
UNION ALL 
SELECT 
3, NULL, 'BB', 'CC', 'DD' 
UNION ALL 
SELECT 
4, 'AA', 'BB', NULL, 'DD' 
UNION ALL 
SELECT 
5, 'AA', 'BB', 'CC', 'DD' 


SELECT * from #thisTest 
select 
ID, 
CASE WHEN BOX1 IS NULL THEN COALESCE(BOX2,BOX3,BOX4) ELSE BOX1 END AS BOX1, 
CASE WHEN BOX1 IS NULL AND BOX2 IS NULL THEN BOX4 WHEN BOX1 IS NULL THEN COALESCE(BOX3,BOX4) ELSE COALESCE(BOX2,BOX3,BOX4) END AS BOX2, 
CASE WHEN BOX1 IS NULL AND BOX2 IS NULL THEN NULL WHEN (BOX1 IS NULL OR BOX2 IS NULL) and BOX3 IS NULL THEN NULL WHEN BOX1 IS NULL OR BOX2 IS NULL THEN COALESCE(BOX3,BOX4) ELSE BOX4 END AS BOX3, 
CASE WHEN BOX1 IS NULL or BOX2 IS NULL OR BOX3 IS NULL THEN NULL ELSE BOX4 END AS BOX4 
from 
#thisTest 
+0

Dies zeigt nur, was für eine schreckliche Idee dies in der Datenbank zu tun ist. Es ist nah, erzeugt aber nicht die gewünschte Leistung. Schau auf payee_ID 5. :) –

+0

Füge folgendes zur Tabelle hinzu und dein Code produziert keine korrekten Ergebnisse: UNION ALLE SELECT 6, NULL, NULL, 'CC', 'DD' – user3294322

+0

Payee_ID 5 ist eigentlich korrekt! Das Problem tritt auf, wenn Sie mit der obigen Kombination "payee_ID 6" hinzufügen. – user3294322

0
IF OBJECT_ID('tempdb..#thisTest') IS NOT NULL DROP TABLE #thisTest 

SELECT 
1 as ID, NULL as BOX1, 'BB' as BOX2, NULL as BOX3, 'DD' as BOX4 
INTO #thisTest 
UNION ALL 
SELECT 
2, 'AA', NULL, NULL, 'DD' 
UNION ALL 
SELECT 
3, NULL, 'BB', 'CC', 'DD' 
UNION ALL 
SELECT 
4, 'AA', 'BB', NULL, 'DD' 
UNION ALL 
SELECT 
5, 'AA', 'BB', 'CC', 'DD' 
UNION ALL 
SELECT 6, NULL, NULL, 'CC', 'DD' 

SELECT * from #thisTest 
select 
ID, 
CASE WHEN BOX1 IS NULL THEN COALESCE(BOX2,BOX3,BOX4) ELSE BOX1 END AS BOX1, 

CASE WHEN BOX1 IS NULL AND BOX2 IS NOT NULL THEN COALESCE(BOX3,BOX4) 
    WHEN BOX1 IS NULL AND BOX2 IS NULL THEN BOX4 
    ELSE COALESCE(BOX2,BOX3,BOX4) END AS BOX2, 

CASE WHEN BOX1 IS NULL AND BOX2 IS NULL AND BOX3 IS NULL THEN BOX4 
    WHEN BOX1 IS NOT NULL AND BOX2 IS NOT NULL THEN COALESCE(BOX3,BOX4) 
    ELSE '' END AS BOX3, 

CASE WHEN BOX1 IS NOT NULL AND BOX2 IS NOT NULL AND BOX3 IS NOT NULL THEN BOX4 ELSE '' END AS BOX4 

from 
#thisTest 
+0

Hat das funktioniert? Ich habe die Arbeit verlassen, kann also nicht testen – scsimon

+0

@scsimon Ja, tut es .. Danke :) – user3294322

+0

Froh, ich könnte helfen. Ich bin froh, dass ich es meistens richtig gemacht habe und war hilfreich – scsimon

0

Ich werde einfach annehmen, die #thisTest Die Tabelle ist wie in den obigen Beispielen ausgefüllt. Keine Notwendigkeit, diesen Code zu duplizieren.

WITH workTable as (
    SELECT 
     ID, 
     ISNULL(BOX1, '') + ISNULL(BOX2, '') + ISNULL(BOX3, '') + ISNULL(BOX4, '') AS Boxes 
    FROM #thisTest 
    ) 
INSERT INTO Table2 (
    Payee_id, 
    Box1, 
    Box2, 
    Box3, 
    Box4, 
    ) 
SELECT 
    ID, 
    ISNULL(SUBSTRING(Boxes, 1, 1), ''), 
    ISNULL(SUBSTRING(Boxes, 2, 1), ''), 
    ISNULL(SUBSTRING(Boxes, 3, 1), ''), 
    ISNULL(SUBSTRING(Boxes, 4, 1), '') 
FROM workTable 

Meine Codierungsphilosophie beinhaltet Code Einfachheit. Wenn das um Größenordnungen langsamer als die anderen Optionen wäre, würde ich es nicht verwenden, aber wenn nicht, wird dies ausführen, was Sie brauchen, ohne mehrere Überprüfungen, welche BOXn-Werte Null sind.

Beachten Sie, dass diese Grundform mit kleinen Änderungen funktioniert, auch wenn Sie 20 BOX-Werte zu komprimieren haben, während eine Logik mit mehreren Bedingungen exponentiell anwächst.

0

@ Laughing.Vergil ist auf dem richtigen Weg, auch wenn seine Syntax ein bisschen weg ist;)

Obwohl nicht in Frage gepostet, werde ich diese Frage beantworten selbst mit CTE einmal im JOIN und auch direkt . :D

Wenn ich Sie richtig verstehe, möchten Sie, dass alle Werte auf die linke Seite der Zeile mit allen NULL-Werten auf der rechten Seite geschoben werden. Ich werde entscheiden, @ Laughing.Vergils Idee zu nehmen, denn wenn die bekannten Werte stabile Länge sind, gibt es keinen Grund, dass der Code furchtbar kompliziert sein muss. d. h. LEN(Box1) = 2

In diesem Beispiel verwende ich die erste von Ihnen definierte Tabelle und stelle mir vor, dass die Einschränkungen in der Anwendung fehlschlagen, um die Operationen CTE zu veranschaulichen.

CREATE TABLE #Example (Payee_ID INT, 
          BOX1 VARCHAR(2) NULL, 
          BOX2 VARCHAR(2) NULL, 
          BOX3 VARCHAR(2) NULL, 
          BOX4 VARCHAR(2) NULL) 
INSERT INTO #Example(Payee_ID, BOX1, BOX2, BOX3, BOX4) 
VALUES (1, NULL, 'BB', NULL, 'DD') 
     , (2, 'AA', NULL, NULL, 'DD') 
     , (3, NULL, 'BB', 'CC', 'DD') 
     , (4, 'AA', 'BB', NULL, 'DD') 
     , (5, 'AA', 'BB', 'CC', 'DD') 
     , (6, NULL, 'CB', NULL, 'DD') -- the bad input 
;WITH C as (
    SELECT 
     Payee_ID 
     , ISNULL(Box1, '') + ISNULL(Box2, '') + ISNULL(Box3, '') + ISNULL(Box4, '') AS BOX 
    FROM #Example 
    ) 
UPDATE A 
    SET 
    BOX1 = IIF(SUBSTRING(Box, 1, 2) = '', NULL, SUBSTRING(Box, 1, 2)) 
    , BOX2 = IIF(SUBSTRING(Box, 3, 2) = '', NULL, SUBSTRING(Box, 3, 2)) 
    , BOX3 = IIF(SUBSTRING(Box, 5, 2) = '', NULL, SUBSTRING(Box, 5, 2)) 
    , BOX4 = IIF(SUBSTRING(Box, 7, 2) = '', NULL, SUBSTRING(Box, 7, 2)) 
FROM #Example A 
INNER JOIN C ON C.Payee_ID = A.Payee_ID 

Ergebnisse

Payee_ID BOX1 BOX2 BOX3 BOX4 
1   BB  DD  NULL NULL 
2   AA  DD  NULL NULL 
3   BB  CC  DD  NULL 
4   AA  BB  DD  NULL 
5   AA  BB  CC  DD 
6   CB  ED  NULL NULL 

nun der spannende Teil. Aktualisieren/Löschen aus einer Tabelle mit CTE s. Nehmen wir an, dass wegen der Funktionsweise der Anwendung nur die erste Box ungültig sein kann.

WITH CTE AS (SELECT * 
      FROM #Example2 
      WHERE BOX1 NOT IN ((LEFT(Box1, 1)) 
           + (LEFT(Box1, 1)))) 
DELETE FROM CTE 

Finale Ergebnisse

Payee_ID BOX1 BOX2 BOX3 BOX4 
1   BB  DD  NULL NULL 
2   AA  DD  NULL NULL 
3   BB  CC  DD  NULL 
4   AA  BB  DD  NULL 
5   AA  BB  CC  DD 

Während dies sehr dumm war, ich hoffe, Sie können sehen, wie die Tabellen hinter dem CTE betroffen sind, was irgendwie cool ist.

Cheers,

+0

Beachten Sie, dass ich auch angenommen habe, dass Payee_ID nur eine Zeile zugeordnet hat. –

Verwandte Themen