2016-06-26 9 views
9

Ok, 4 Stunden Codierung und nur 6 Stunden Suche ... und ich bin nicht besser dran als zu Beginn. Hier ist mein Problem. Ich habe eine Tabelle (tmpShell) und es hat 12 Spalten. Es handelt sich um eine Basistabelle ohne Einschränkungen, die für temporäre Berichte verwendet wird. Wenn wir Daten einfügen, muss ich eine ID-Nummer (PatientId) und alle Spalten NAMES extrahieren, wo der Wert für diese PatientId Null ist.Auswählen von Spaltennamen, deren Werte NULL sind

Beispiel:

 
PatientId    Fname    Lname      DOB 
123455       Sam      NULL       NULL
2345455      NULL     Doe        1/1/1980
09172349     John     Jone       NULL

Was ich zurückkehren will, ist:

 
PatientId    ErrorMsg 
123455       Lname,DOB
2345455      Fname
09172349     DOB

Natürlich, wenn alle Spalten einen Wert haben, würde die errormsg null sein.

Ich habe über 300 verschiedene Teile des Codes versucht und sind gescheitert, aber in der Nähe zu sein scheinen ich bekommen kann. Leider gibt dies nur jede Spalte zurück, nicht die Nullen.

 
    ALTER PROC [sp_aaShowAllNullColumns] 
     @tableName VARCHAR(255) 
    AS 
     BEGIN 
      SET NOCOUNT ON;

DECLARE @sql NVARCHAR(4000); DECLARE @cols NVARCHAR(4000); DECLARE @tcols TABLE ([colbit] NVARCHAR(255)); --DECLARE @tablename VARCHAR(255) = 'tmpShell'; INSERT @tcols SELECT 'count(' + [columns].[name] + ') as ' + [columns].[name] + ', ' AS [colbit] FROM [sys].[columns] WHERE [columns].[object_id] = OBJECT_ID(@tableName); SELECT @cols = COALESCE(@cols, ', ', '') + [@tcols].[colbit] FROM @tcols; SELECT @cols = SUBSTRING(@cols, 1, (LEN(@cols) - 1)); SELECT @cols = ISNULL(@cols, ''); SELECT @sql = 'select patientid, count(*) as Rows' + @cols + ' from ' + @tableName + ' group by patientid having count(*) > 0'; CREATE TABLE [tmpShell2] ( [patientid] VARCHAR(15) ,[Rows] CHAR(2) ,[Rn] CHAR(2) ,[patId] CHAR(2) ,[fname] CHAR(2) ,[lname] CHAR(2) ,[dob] CHAR(2) ,[addr1] CHAR(2) ,[city] CHAR(2) ,[state] CHAR(2) ,[zip] CHAR(2) ,[country] CHAR(2) ,[psite] CHAR(2) ,[csite] CHAR(2) ,[ssite] CHAR(2) ,[scode] CHAR(2) ,[sfid] CHAR(2) ,[taskid] CHAR(2) ,[errormsg] CHAR(2) ); INSERT INTO [tmpShell2] EXEC [sys].[sp_executesql] @sql; DECLARE @tbl VARCHAR(255) = 'tmpShell2'; SELECT DISTINCT [TS].[patientid] , STUFF(( SELECT DISTINCT ', ' + [C].[name] FROM [tmpShell2] AS [TS2] JOIN [sys].[columns] AS [C] ON [C].[object_id] = OBJECT_ID(@tbl) WHERE [C].[name] NOT IN ('SFID', 'TaskId', 'ErrorMsg') AND [C].[name] IS NOT NULL FOR XML PATH('') ), 1, 1, '') FROM [tmpShell2] AS [TS]; DROP TABLE [dbo].[tmpShell2]; END; GO EXEC [sp_aaShowAllNullColumns] 'tmpShell'; </pre>
+0

Müssen Sie dies auf eine unbekannte Anzahl von Tabellen oder nur diese tun? –

+0

Wie groß ist die Wahrscheinlichkeit, dass sich die Spalten (mit Ausnahme des Schlüssels) in dieser Tabelle ändern oder dass es Spalten gibt, in denen es Ihnen egal ist, ob es eine Null gibt? –

+0

Ja, die Anzahl der Tabellen ist unbekannt und die Spalten variieren von Tabelle zu Tabelle. Die Wahrscheinlichkeit, dass sich irgendetwas ändert, ist sehr gering – RazorSharp

Antwort

3

Wie wäre es mit so etwas?

SELECT 
a.PatientID 
, CASE a.tmpCol 
    WHEN '' THEN NULL 
    ELSE STUFF(a.tmpCol,1,1,'') 
END AS ErrorMsg 
FROM 
(
SELECT 
    PatientID 
    , CASE WHEN FirstName IS NULL THEN ',FirstName' ELSE '' END 
    + CASE WHEN LastName IS NULL THEN ',LastName' ELSE '' END 
    + CASE WHEN DOB IS NULL THEN ',DOB' ELSE '' END AS tmpCol 
FROM 
    <tableName> 
) a; 
+0

Ich benutze dies für jetzt, aber ich würde eine dynamischere Art und Weise lieben, die für verschiedene Tabellen und Spaltennamen flexibel ist. – RazorSharp

+0

Ich habe unten eine Antwort hinzugefügt, von der ich glaube, dass sie für Tabellen- und Spaltennamen flexibel ist. – DVT

8

Ich glaube, Sie über komplizierte Dinge.

können Sie versuchen, CASE EXPRESSION mit:

SELECT t.patientID, 
     CASE WHEN t.fname is NULL THEN 'Fname,' ELSE '' END + 
     CASE WHEN t.Lname is NULL THEN 'Lname,' ELSE '' END + 
     CASE WHEN t.DOB is NULL THEN 'DOB,' ELSE '' END 
     ..... as ErrorMsg 
FROM YourTable t 

Dies mit einem unnötigen Komma am Ende der errorMsg führen wird, es zu behandeln, dies zu tun:

 REPLACE(CASE... + 
       CASE... + 
       CASE WHEN t.DOB is NULL THEN 'DOB,' ELSE '' END 
       ..... + ' ') ', ','') as ErrorMsg 

Dies sind die machen Das letzte Komma ist eindeutig, weil es ein Leerzeichen verketten und sicherstellen wird, dass es nur gelöscht wird.

+0

Wie planen Sie, den Fall zu behandeln, wo nur 'Fname' für einen bestimmten Datensatz erscheint? Dann wird es ein baumelndes Komma haben. –

+0

@TimBiegeleisen Gefällt mir .. – sagi

2

Sie können eine Pivot-Abfrage verwenden, um das gewünschte Ergebnis zu erhalten. Die folgende Abfrage sollte Ihrer gewünschten Ausgabe entsprechen:

SELECT PatientId, 
    CONCAT(CASE WHEN Fname IS NULL THEN 'Fname ' ELSE '' END, 
      CASE WHEN Lname IS NULL THEN 'Lname ' ELSE '' END, 
      CASE WHEN DOB IS NULL THEN 'DOB' ELSE '' END) 
FROM yourTable 
+0

Er wollte die Liste mit Kommas, 14 Spalten ohne ein Komma werden nicht lesbar sein. – sagi

1

Hier ist ein SQLfiddle auf https://stackoverflow.com/a/38036046/2314737 mit der Handhabung des

http://sqlfiddle.com/#!9/708796/1 Kommata basierend

SELECT PatientId, 
    REPLACE(RTRIM(CONCAT(CASE WHEN Fname IS NULL THEN 'Fname ' ELSE '' END, 
      CASE WHEN Lname IS NULL THEN 'Lname ' ELSE '' END, 
      CASE WHEN DOB IS NULL THEN 'DOB' ELSE '' END)), 
      ' ',',') 
FROM YourTable 
+0

hi @ sagi danke für dein Feedback. Wenn alle Felder nicht NULL sind, wird es einen leeren Platz geben, ich denke, dass man eine andere Auswahl treffen muss, um Zeilen mit leeren Räumen auszuschließen. – user2314737

+0

@sagi kümmert sich das RTRIM vor dem REPLACE nicht darum? – user2314737

+0

Ja, das habe ich leider vermisst. – sagi

0

Dies ist eine gespeicherte Prozedur, die in den Schemanamen, Tabellennamen und Spaltennamen nehmen, dann produzieren das gewünschte Ergebnis.

ALTER PROCEDURE [dbo].[DynamicErrorProducing] 
@schema_name NVARCHAR(100), 
@table_name NVARCHAR(100), 
@column_name NVARCHAR(100) 
AS 
BEGIN 
DECLARE @countTable TINYINT; 
DECLARE @countColumn TINYINT; 
DECLARE @string NVARCHAR(MAX); 
DECLARE @sqlString NVARCHAR(MAX); 

SET @countTable=0; 

SELECT 
    @countTable=COUNT(*) 
FROM 
    sys.tables 
WHERE 
    SCHEMA_NAME(schema_id)[email protected]_name 
    AND [email protected]_name; 

-- If there is no table as described, quit with an error 
IF (@countTable = 0) 
    RETURN 0; 

SET @countColumn=0; 

SELECT 
    @countColumn=COUNT(*) 
FROM 
    sys.columns 
WHERE 
    object_id = OBJECT_ID(@schema_name+'.'[email protected]_name) 
    AND [email protected]_name; 

IF (@countColumn<> 1) 
    RETURN; 

SELECT 
    @countColumn=COUNT(*) 
FROM 
    sys.columns 
WHERE 
    object_id = OBJECT_ID(@schema_name+'.'[email protected]_name) 
    AND name<>@column_name; 

IF (@countColumn<1) 
    RETURN; 

SELECT @string=STUFF(
    (
    SELECT 
     '+ CASE WHEN '+name+' IS NULL THEN '''' ELSE '','+name+''' END ' 
    FROM 
     sys.columns 
    WHERE 
     object_id = OBJECT_ID(@schema_name+'.'[email protected]_name) 
     AND name<>@column_name 
    FOR XML PATH('')) 
    ,1,2,''); 


SET @sqlString=N' 
SELECT 
    a.'[email protected]_name+' 
    , CASE WHEN a.tmpCol='''' THEN NULL ELSE STUFF(a.tmpCol,1,1,'''') END AS ErrMsg 
FROM 
(
SELECT 
    '[email protected]_name+' 
    ,'[email protected]+' AS tmpCol 
FROM 
    '[email protected]_name+'.'[email protected]_name+' 
) a'; 

EXEC sp_executesql 
    @[email protected]; 

END 


GO 
Verwandte Themen