2016-12-09 4 views
1

Wir haben ein Projekt, in dem wir dem Benutzer die Möglichkeit bieten sollen, eigene benutzerdefinierte Spalten zu verschiedenen Tabellen hinzuzufügen.T-Sql Abfrage mit dynamischer (unbekannter) Anzahl von Spalten

Edit: das sind 2 Tabellen, nicht eins.

**Products** 
ProductId 
Name 
Price 
Date 
UserId 

**ProductsCustomColumns** 
ProductId 
ColumnName 
ColumnValue 

EDIT: Bitte beachten Sie, dass die dynamischen Spalten als Werte aufgezeichnet werden und wir wissen nicht, die Anzahl der diese ... es 0 oder 200 oder eine beliebige sein kann. Hier

ein Beispiel: enter image description here Nun, wenn wir die Produkte Tabellen abfragen wir alle vordefinierten Spalten angezeigt werden sollen und nach ihnen alle benutzerdefinierten Spalten. Offensichtlich kann jeder Benutzer eine eigene Anzahl von Spalten mit Werten und Namen haben.

SELECT *, (and the custom columns) FROM Products WHERE UserId = 3 AND ProductId = 1 

Hier gibt es 2 Fragen:

  1. , dass eine gute Lösung aus Performance-Sicht sein würde, oder es gibt bessere Ansatz für die dynamische Spalten Anforderung zu lösen?

  2. Wie kann ich eine Abfrage erstellen, die alle Datensätze aus ProductsCustomColumns für gegebene userId und productId und fügen Sie die Einträge als Spalten der Abfrage lesen konnte?

Danke.

+0

Ist ProductsCustomColumns eine separate Tabelle? –

+0

Ja, separate Tabelle. –

Antwort

2

Sie dynamische Abfrage

DECLARE @COLUMNS VARCHAR(MAX)='', @QRY VARCHAR(MAX); 

SELECT @COLUMNS = @COLUMNS +COLUMN_NAME +',' FROM 
INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='Products' 

SELECT @COLUMNS =SUBSTRING (@COLUMNS,1 ,LEN(@COLUMNS)-1) 

SELECT @QRY ='SELECT '[email protected] + ' FROM Products WHERE UserId = 3 AND ProductId = 1' 
EXEC (@QRY) 

EDIT schreiben müssen, tun: Von Ihrer Kommentare & Edited Frage

Schema I angenommen von Ihrer Frage

CREATE TABLE Products (
ProductId INT, 
Name VARCHAR(250), 
Price DECIMAL(18,2), 
DateS DATETIME, 
UserId INT) 

INSERT INTO Products 
SELECT 1,'Oil Product', 2000, GETDATE(), 3 
UNION ALL 
SELECT 2,'Amway', 600, GETDATE(), 2 
UNION ALL 
SELECT 3,'Thermal', 5000, GETDATE(), 1 
UNION ALL 
SELECT 4,'Oil Product', 500, GETDATE(), 4 



CREATE TABLE ProductsCustomColumns 
(
ProductId INT , 
ColumnName VARCHAR(200), 
ColumnValue VARCHAR(15)) 

INSERT INTO ProductsCustomColumns 
SELECT 1, 'Licence_No', '1545' 
UNION ALL 
SELECT 1, 'Location ', 'Atlanta' 
UNION ALL 
SELECT 2, 'Qty ', '5' 
UNION ALL 
SELECT 3, 'Gross', '80000' 

Jetzt Ihr Dynamic Code geht hier

DECLARE @COLUMN_PCC VARCHAR(MAX)='', @PRODUCT_ID INT=1,@USER_ID INT=3, @QRY VARCHAR(MAX) ; 

--preparing Custom Column Name List with comma ',' 
SELECT @COLUMN_PCC = @COLUMN_PCC+ [COLUMNNAME] +',' FROM ProductsCustomColumns 
WHERE ProductId= @PRODUCT_ID 
SELECT @COLUMN_PCC =SUBSTRING(@COLUMN_PCC,1,LEN(@COLUMN_PCC)-1) 


--Preparing Dynamic Query 
SELECT @QRY =' SELECT P.*, AV.* FROM Products P 
INNER JOIN 
(
SELECT * FROM (
SELECT * FROM ProductsCustomColumns WHERE ProductId= '+CAST(@PRODUCT_ID AS VARCHAR(50))+' 
) 
AS A 
PIVOT 
(
MAX (COLUMNVALUE) 
FOR [COLUMNNAME] IN ('[email protected]_PCC +') 
)AS PVT 
)AS AV ON P.ProductId= AV.ProductId 
AND P.UserId='++CAST(@USER_ID AS VARCHAR(50))+' 
' 

EXEC (@QRY) 

und das Ergebnis wird

+-----------+-------------+---------+-------------------------+--------+-----------+------------+----------+ 
| ProductId | Name  | Price |   DateS   | UserId | ProductId | Licence_No | Location | 
+-----------+-------------+---------+-------------------------+--------+-----------+------------+----------+ 
|   1 | Oil Product | 2000.00 | 2016-12-09 18:06:24.090 |  3 |   1 |  1545 | Atlanta | 
+-----------+-------------+---------+-------------------------+--------+-----------+------------+----------+ 
+0

Die dynamischen Spalten stammen nicht aus anderen Tabellenspalten, sie sind Datensätze in der zweiten Tabelle. –

+0

@st_stefanov Bitte überprüfen Sie jetzt ed. Ans. –

+0

Sieht toll aus, lass es mich versuchen! –

0

Sie benötigen dynamische SQL keine andere Möglichkeit, diese

DECLARE @sql  VARCHAR(max), 
     @cust_col VARCHAR(max) 

SET @cust_col = (SELECT Quotename(CustomColumns) + ',' 
       FROM ProductsCustomColumns 
       FOR xml path('')) 

SELECT @cust_col = LEFT(@cust_col, Len(@cust_col) - 1) 

SET @sql = 'SELECT *, ' + @cust_col + ' FROM Products WHERE UserId = 3 AND ProductId = 1' 

EXEC (@sql) 
+0

Wenn ich es ausführe, zeigt es einen Fehler an: Nachricht 207, Ebene 16, Status 1, Zeile 1 Ungültiger Spaltenname "Comment1". Hinweis: Kommentar1 ist der Wert in CustomColumn. –

1

Im Allgemeinen ist es eine sehr schlechte Idee, individuelle Daten in zusätzlichen Spalten Ihrer Haupttabelle hinzuzufügen. Stellen Sie sich nur 100 Kunden vor, die das verwenden. Alle haben unterschiedliche Tabellenschemata und Sie möchten für alle ein Update-Skript schreiben?

Es ist ein Schmerz im Nacken, wenn Sie sich mit Resultsets beschäftigen müssen, bei denen Sie die Struktur nicht im Voraus kennen!

Sie haben mehrere Möglichkeiten:

  • Fügen Sie eine Spalte vom Typ XML. Der Vorteil: Das Resultset ist fix. Sie brauchen nur eine kundenspezifische Regel, wie man das XML interpretiert.Sie können dies mit einer Inline-Tabellenwertfunktion lösen. Übergeben Sie das XML und rufen Sie eine abgeleitete Tabelle zurück. Rufen Sie diese mit CROSS APPLY und Sie sind aus ...

  • eine neue Tabelle hinzufügen mit dem customerID und Key-Value-Paare

  • Wenn die zusätzlichen Daten nicht völlig anders ist, fügen Sie einige der Spalten zu Ihrer Haupttabelle als SPARSE Spalten

+0

Eigentlich sind das 2 Tische. –

+0

Und wir haben auch über die vordefinierte, große Anzahl von Spalten nachgedacht ... –

Verwandte Themen