it-swarm.com.de

Ist es möglich, eine Spalte basierend auf dem Ergebnis eines select + where zu aliasen?

Ich habe einen Tisch wie diesen:

TB1:

COD | A001 | A002 | A003
 1    cars   baby   nasa

und dann eine zweite Tabelle:

TB2:

COD | NO_COL_TB1 | DESCRIPTION |
 1  |    A001    |  Something
 2  |    A002    |   lasagna

Was ich versuche zu tun, ist so etwas (offensichtlich funktioniert das nicht)

select A001 as (select description from TB2 WHERE no_col_tb1= A001 )
      ,A002 AS (select description from TB2 WHERE no_col_tb1= A002 )
from TB1

ich habe es mit inneren Joins und etwas dynamischem SQL versucht, aber ich kann einfach nicht in einer Logik dafür denken. Es gibt einige Fragen dazu, aber keine davon könnte mir helfen. Ich denke, dass dies mit einer einzelnen Anweisung unmöglich und nur mit Dynamic SQL möglich ist.

BEARBEITEN:

Das richtige Ergebnis wäre:

SELECT COD,
       TB1.A001 AS 'Something',
       TB1.A002 AS 'Lasagna'
FROM TB1

und das Ergebnis wäre:

COD |SOMETHING | LASAGNA |
 1      cars       baby
6
Racer SQL

Tut mir leid zu sagen, aber es ist schwierig, mit Ihrer Tabellenstruktur zu arbeiten, wenn Sie überlegen, was Sie tun möchten. Es gibt verschiedene Möglichkeiten, wie Sie wahrscheinlich das Ergebnis erhalten können. Eine Möglichkeit wäre, UNPIVOT und PIVOT zu verwenden, aber es ist hässlich.

Sie können beginnen, indem Sie UNPIVOT die Daten in TB1 Von Ihren Spalten in Zeilen eingeben:

select *
from tb1 t1
unpivot 
(
    val
    for col in (A001, A002, A003)
) u

Dadurch werden die Daten im folgenden Format zurückgegeben:

| COD |  val |  col |
|-----|------|------|
|   1 | cars | A001 |
|   1 | baby | A002 |
|   1 | nasa | A003 |

Dann könnten Sie dieses Ergebnis nehmen und es mit TB2 Verbinden:

select 
    d.COD,
    d.val,
    t2.DESCRIPTION
from
(
    select *
    from tb1 t1
    unpivot 
    (
        val
        for col in (A001, A002, A003)
    ) u
)d
inner join tb2 t2
    on d.col = t2.NO_COL_TB1;

Welches ergibt das Ergebnis:

| COD |  val | DESCRIPTION |
|-----|------|-------------|
|   1 | cars |   Something |
|   1 | baby |     lasagna |

Jetzt haben Sie Ihre neuen Spaltennamen in den Zeilen Description und val in Zeilen, aber Sie möchten sie in Spalten, sodass Sie jetzt die Funktion PIVOT darauf anwenden können:

select *
from
(
    select 
        d.COD,
        d.val,
        t2.DESCRIPTION
    from
    (
        select *
        from tb1 t1
        unpivot 
        (
            val
            for col in (A001, A002, A003)
        ) u
    )d
    inner join tb2 t2
        on d.col = t2.NO_COL_TB1
) x
pivot
(
    max(val)
    for description in (Something, Lasagna)
) p;

Dies erzeugt das gewünschte Endergebnis:

| COD | Something | Lasagna |
|-----|-----------|---------|
|   1 |      cars |    baby |

Das alles ist großartig, wenn Sie alle Spalten kennen, die Sie für UNPIVOT und dann für PIVOT benötigen. Wenn Sie dies nicht tun, müssen Sie dynamisches SQL verwenden, um das Problem zu lösen. Welches wird ungefähr so ​​aussehen:

DECLARE 
    @colsUnpivot AS NVARCHAR(MAX),
    @colsPivot AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @colsUnpivot 
  = stuff((select ','+quotename(C.column_name)
           from information_schema.columns as C
           where C.table_name = 'tb1' and
                 C.column_name like 'A%'
           for xml path('')), 1, 1, '')

select @colsPivot 
  = stuff((select ','+quotename([DESCRIPTION])
           from Tb2
           for xml path('')), 1, 1, '')


set @query = 'select *
            from
            (
                select 
                    d.COD,
                    d.val,
                    t2.DESCRIPTION
                from
                (
                    select *
                    from tb1 t1
                    unpivot 
                    (
                        val
                        for col in ('+ @colsUnpivot +')
                    ) u
                )d
                inner join tb2 t2
                    on d.col = t2.NO_COL_TB1
            ) x
            pivot
            (
                max(val)
                for description in ('[email protected]+')
            ) p;';

exec sp_executesql @query;

Es ist lang, aber es sollte Ihnen das gleiche Ergebnis bringen. ( dbfiddle demo )

25
Taryn
DECLARE @SQL NVARCHAR(MAX)

SELECT @SQL = STUFF(
    ( SELECT ', ' + QUOTENAME(C.COLUMN_NAME) + ' AS ' + QUOTENAME(F.DESCRICAO)
FROM INFORMATION_SCHEMA.COLUMNS C 
    INNER JOIN TABBASE F ON C.COLUMN_NAME = F.NO_COL_TABBASE
WHERE C.TABLE_NAME = 'TABELA_ENTRADA'
ORDER BY C.ORDINAL_POSITION FOR XML PATH('')),1,2,'')

SELECT @SQL = 'SELECT ' + @SQL + ' FROM tabela_entrada'

PRINT @SQL

EXECUTE(@SQL)

Gibt es einen besseren Weg als diesen? Ich wusste nicht, dass ich dafür STUFF verwenden kann. Ich habe diese Abfrage unter diese Microsoft-Seite gefunden.

4
Racer SQL

Ich habe dies getan, als ich einige dynamische Daten für einen Seriendruck in Word erstellt habe. Die Spaltennamen müssen zur Kompilierungszeit bekannt sein, daher müssen Sie dynamisches SQL verwenden.

Wenn Sie viele Spalten oder Spalten mit großen Größen benötigen, erreichen Sie die Zeilengrößenbeschränkung für die Funktion PIVOT. In diesem Fall müssen Sie den Pivot mit GROUP BY Ausführen.

DECLARE @Pivot table ( [RowID] int, [ColumnName] nvarchar(50), [ColumnValue] nvarchar(50) );

INSERT INTO @Pivot VALUES (1,'Something','cars'), (1,'lasagna','baby'), (2,'Something','other'), (2,'lasagna','data');

SELECT 
    [RowID],
    [Something] = MAX(CASE WHEN [ColumnName] = 'Something' THEN [ColumnValue] END),
    [lasagna] = MAX(CASE WHEN [ColumnName] = 'lasagna' THEN [ColumnValue] END)
FROM 
    @Pivot
GROUP BY 
    [RowID];

Für Ihre Datenstruktur müssen Sie das Pivot aufheben, um die Tabelle mit Ihren Spaltennamen zu verknüpfen. Ich bevorzuge dies mit einem Kreuz anwenden.

DECLARE @TB1 table ( [COD] int, [A001] varchar(50), [A002] varchar(50), [A003] varchar(50) );
DECLARE @TB2 table ( [COD] int, [NO_COL_TB1] varchar(50), [DESCRIPTION] varchar(50) );

INSERT INTO @TB1 values (1,'cars','baby','nasa')
INSERT INTO @TB2 values (1,'A001','Something'), (2,'A002','lasagna')


CREATE TABLE #LargePivotData ( [RowID] int not null, [ColumnName] nvarchar(128) not null, [ColumnValue] nvarchar(max) ); 
-- QUOTENAME will return null for anything longer than 128


INSERT INTO 
    #LargePivotData
SELECT 
    [RowID] = [TB1].[COD],
    [ColumnName] = [DESCRIPTION],
    [ColumnValue] = [TB1_Value]
FROM 
    @TB1 AS [TB1]
    --unpivot
    CROSS APPLY (VALUES
        ('A001', [A001]),
        ('A002', [A002]),
        ('A003', [A003])
    ) AS [TB1_Unpivot]([TB1_Column], [TB1_Value])
    INNER JOIN @TB2 AS [TB2]
        ON [TB1_Unpivot].[TB1_Column] = [TB2].[NO_COL_TB1]


DECLARE @Columns nvarchar(max), @ColumnValues nvarchar(max);

WITH [ColumnNameValues] AS (
    SELECT DISTINCT
        [Name] = QUOTENAME([ColumnName]),
        [Value] = QUOTENAME([ColumnName]) + N' = MAX(CASE WHEN [ColumnName] = N' + QUOTENAME([ColumnName], '''') + N' THEN [ColumnValue] END)'
    FROM 
        #LargePivotData
)
SELECT 
    @Columns = COALESCE(@Columns + N',' + [Name], [Name]),
    @ColumnValues = COALESCE(@ColumnValues + N',' + [Value], [Value])
FROM 
    [ColumnNameValues]
ORDER BY
    [Name];

DECLARE @Sql nvarchar(max) = N'
    WITH [PivotedData] AS (
        SELECT
            [RowID],
            ' + @ColumnValues + N'
        FROM
            #LargePivotData
        GROUP BY
            [RowID]
    )
    SELECT 
        [RowID],
        ' + @Columns + N'
    FROM 
        [PivotedData]
        -- join on any additional tables
    ';

--PRINT @Sql;

DECLARE @params nvarchar(4000) = N''; -- for additional parameters used in @Sql

EXEC sp_executesql @Sql, @params;

DROP TABLE #LargePivotData;
0
Nicholas