我们有一个项目,我们应该为用户提供将自己的自定义列添加到各种表的可能性。
编辑:这些是2个表,而不是一个。
**Products**
ProductId
Name
Price
Date
UserId
**ProductsCustomColumns**
ProductId
ColumnName
ColumnValue
编辑:请注意,动态列会记录为值,我们不知道这些值的计数......它可以是0或200或任何。
这是一个例子: 现在,当我们查询产品表时,我们要显示所有预定义列,然后是所有自定义列。 显然,每个用户都可以拥有自己的带有值和名称的列数。
SELECT *, (and the custom columns) FROM Products WHERE UserId = 3 AND ProductId = 1
以下是2个问题:
从性能的角度来看,这是一个很好的解决方案还是有更好的解决动态列要求的方法?
如何创建一个查询,可以读取ProductsCustomColumns
给定userId
和productId
的所有记录,并将记录作为列附加到查询中?
感谢。
答案 0 :(得分:2)
您需要编写动态查询
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 '+@COLUMNS + ' FROM Products WHERE UserId = 3 AND ProductId = 1'
EXEC (@QRY)
编辑:来自您的评论&编辑问题
我从你的问题中假设的模式
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'
现在你的动态代码就在这里
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 ('+@COLUMN_PCC +')
)AS PVT
)AS AV ON P.ProductId= AV.ProductId
AND P.UserId='++CAST(@USER_ID AS VARCHAR(50))+'
'
EXEC ( @QRY)
结果将是
+-----------+-------------+---------+-------------------------+--------+-----------+------------+----------+
| 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 |
+-----------+-------------+---------+-------------------------+--------+-----------+------------+----------+
答案 1 :(得分:1)
通常,在主表的其他列中添加自定义数据是一个非常糟糕的主意。想象一下有100个客户使用它。它们都有不同的表模式,您可以为所有这些模式编写更新脚本吗?
如果您必须事先处理不了解结构的结果集,这是一个痛苦的问题!
您有多种选择:
添加一列XML
类型的列。优点:结果集已修复。您只需要一个客户特定的规则,如何解释XML。您可以使用内联表值函数来解决此问题。传入XML并返回派生表。请使用CROSS APPLY
调用此信息,然后您就出局了......
添加一个包含customerID和Key-Value-Pairs的新表
如果其他数据不完全不同,请将一些列添加到主表中SPARSE
列
答案 2 :(得分:0)
你需要动态sql,没有其他方法可以做到这一点
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)