【发布时间】:2016-09-16 05:55:34
【问题描述】:
我正在处理一个动态查询,它允许我在数据库表中定义字段类型,然后提取在创建仪表板期间选择的用户定义字段列表以及为每个选择的值逻辑运算符。
例如,用户可以选择field1,即employeeID。然后他们可以提供他们想要搜索的 ID,它会将 fieldID 和 fieldValue 存储在一个表中,以便我们需要渲染数据时使用。
现在根据选择的字段,我可能需要连接另一个表以获取更多信息,例如员工姓名。
虽然这很简单,但当必须针对多个可能的表连接值时,棘手的部分就会发挥作用。如果我存储了一个employeeID,我会将该字段与员工表连接起来。但是,如果我存储了 storeID,则需要将该字段与 stores 表连接起来。
这是我在到达终点并意识到自己陷入困境之前的想法。基本上,我会说“如果这个字段是人员表isPeople=1,那么加入我们的employeeTable。
如果此字段为isTool=1,请加入我们的工具表。
我基本上有一个fieldType 和一个fieldValue,根据类型,我需要根据我存储的值加入一个特定的表。
当我处理这个使其成为动态 sql 时,我意识到我不能使用 fl.* 字段来创建我的 IF 条件。
即。 IF (fl.isPeople =1) BEGIN ... JOIN Employee Table ... END
我认为采用动态方法是做到这一点的唯一方法,但现在我想不出解决问题的方法。
结论...
我正在尝试根据条件连接表和查询字段。由于我在正常的存储过程中似乎无法做到这一点,所以我尝试动态地做到这一点并最终出现在这里,我试图解释这个非常混乱的问题。
如果我可以进一步澄清,请告诉我。
更新:
USE [red]
GO
/****** Object: StoredProcedure [dbo].[ti2_fetch_dashboard] Script Date: 9/15/2016 9:55:39 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Carl
-- Create date: Sept 13, 2016
-- Description: Fetch Single Dashboard for Editing
-- =============================================
ALTER PROCEDURE [dbo].[ti2_fetch_dashboard_test]
@dashboardID INT, @SQL NVARCHAR(MAX) = ''
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Fetch our dashboard
SELECT @SQL = 'SELECT d.dashboardID,
d.dashboardOwner,
e.PreferredName AS ownerFirst,
e.LastName AS ownerLast,
e.NTID AS ownerNTID,
d.dashboardTitle,
d.dashboardDescription,
d.dashboardType,
d.creator,
d.timestamp,
d.lastUpdate,
d.isDeleted,
(SELECT sub.QID AS subscriberQID,
e.PreferredName AS subscriberFirst,
e.LastName AS subscriberLast,
e.NTID AS subscriberNTID
FROM dbo.ti_dashboard_subscribers AS sub
LEFT OUTER JOIN
dbo.EmployeeTable AS e
ON sub.QID = e.QID
WHERE sub.dashboardID = d.dashboardID
FOR XML PATH (''options''), ELEMENTS, TYPE, ROOT (''subscribers'')),
(SELECT f.fid,
f.fieldID,
f.[order],
cfg.primaryAllowed,
cfg.secondaryAllowed,
cfg.exportAllowed,
mf.fieldName,
mf.placeholder
FROM dbo.ti_dashboards_fields AS f
INNER JOIN
dbo.ti_dashboard_field_types AS ft
ON f.typeID = ft.fieldTypeID
INNER JOIN
dbo.ti_dashboard_master_fields_config AS cfg
ON f.fieldID = cfg.fieldID
INNER JOIN
dbo.ti_dashboards_master_fields AS mf
ON mf.fieldID = f.fieldID
WHERE f.dashboardID = d.dashboardID
AND ft.fieldTypeName = ''Primary''
ORDER BY f.[order] ASC
FOR XML PATH (''fields''), ELEMENTS, TYPE, ROOT (''primaryFields'')),
(SELECT f.fid,
f.fieldID,
f.[order],
cfg.primaryAllowed,
cfg.secondaryAllowed,
cfg.exportAllowed,
mf.fieldName,
mf.placeholder
FROM dbo.ti_dashboards_fields AS f
INNER JOIN
dbo.ti_dashboard_field_types AS ft
ON f.typeID = ft.fieldTypeID
INNER JOIN
dbo.ti_dashboard_master_fields_config AS cfg
ON f.fieldID = cfg.fieldID
INNER JOIN
dbo.ti_dashboards_master_fields AS mf
ON mf.fieldID = f.fieldID
WHERE f.dashboardID = d.dashboardID
AND ft.fieldTypeName = ''Secondary''
ORDER BY f.[order] ASC
FOR XML PATH (''fields''), ELEMENTS, TYPE, ROOT (''secondaryFields'')),
(SELECT f.fid,
f.fieldID,
f.[order],
cfg.primaryAllowed,
cfg.secondaryAllowed,
cfg.exportAllowed,
mf.fieldName,
mf.placeholder
FROM dbo.ti_dashboards_fields AS f
INNER JOIN
dbo.ti_dashboard_field_types AS ft
ON f.typeID = ft.fieldTypeID
INNER JOIN
dbo.ti_dashboard_master_fields_config AS cfg
ON f.fieldID = cfg.fieldID
INNER JOIN
dbo.ti_dashboards_master_fields AS mf
ON mf.fieldID = f.fieldID
WHERE f.dashboardID = d.dashboardID
AND ft.fieldTypeName = ''Export''
ORDER BY f.[order] ASC
FOR XML PATH (''fields''), ELEMENTS, TYPE, ROOT (''exportFields'')),
(SELECT l.[fieldID],
-- Get the details of each of those fields
(SELECT fl.queryField,
fl.allowMultiple,
fl.isPeople,
fl.isDate,
fl.isSelect,
fl.isInput,
fl.isTool,
fl.selectOptions,
-- Get the values associcated with the fields
(SELECT dv.value';
-- If fl.isPeople = 1
SELECT @SQL += ', e.PreferredName AS FirstName, e.LastName, e.NTID, e.QID ';
-- If fl.isTool = 1
SELECT @SQL += ', t.toolName, t.toolType ';
-- Primary Table
SELECT @SQL += 'FROM dbo.ti_dashboards_logic AS dv ';
-- If fl.isPeople = 1
SELECT @SQL += 'LEFT OUTER JOIN dbo.EmployeeTable AS e ON dv.value = e.QID ';
-- If fl.isTool = 1
SELECT @SQL += 'LEFT OUTER JOIN ti_tools AS t ON dv.value = t.tool ';
-- Rest of Statement
SELECT @SQL += 'WHERE dv.fieldID = l.fieldID
AND dv.dashboardID = d.dashboardID
FOR XML PATH (''data''), TYPE, ELEMENTS, ROOT (''values''))
FROM dbo.ti_dashboard_master_fields_config AS fl
WHERE fl.fieldID = l.fieldID
AND l.dashboardID = d.dashboardID
FOR XML PATH (''fields''), TYPE, ELEMENTS, ROOT (''logicMeta''))
FROM [red].[dbo].[ti_dashboards_logic] AS l
WHERE l.dashboardID = d.dashboardID
GROUP BY l.fieldID, l.dashboardID
FOR XML PATH (''fields''), TYPE, ELEMENTS, ROOT (''logicFields'')),
(SELECT sdb.dashboardID ,
sdb.fieldID ,
sdb.sort ,
sdb.[order] ,
mf.fieldName
FROM dbo.ti_dashboards_sorting AS sdb
JOIN dbo.ti_dashboard_master_fields_config AS sf
ON sdb.fieldID = sf.fieldID
JOIN dbo.ti_dashboards_master_fields AS mf
ON sf.fieldID = mf.fieldID
WHERE sdb.dashboardID = d.dashboardID
ORDER BY sdb.[order] ASC
FOR XML PATH (''fields''), TYPE, ELEMENTS, ROOT (''sortingFields'')
)
FROM dbo.ti_dashboards AS d
LEFT OUTER JOIN
dbo.EmployeeTable AS e
ON d.dashboardOwner = e.QID
WHERE d.dashboardID = @_dashboardID
AND d.isDeleted = 0
FOR XML PATH (''data''), ELEMENTS, TYPE, ROOT (''root'')';
EXEC sp_executesql @SQL, N'@_dashboardID INT', @_dashboardID = @dashboardID
END
【问题讨论】:
-
发布您的代码(不是图片)
-
我认为您实际上可能会从使用 ORM 工具中受益,因此您可以在代码层中进行更多动态查询,或者您可以使用多个查询并在几次访问数据库中提取数据,而不是试图一口气完成所有工作....如果您的数据集有点大,您很快就会遇到性能问题。
-
您是否还可以向用户提供所有字段并将其留空(
NULL)并在连接条件中检查?这样,您始终可以连接所有表,但仅限于使用的参数。
标签: sql sql-server tsql stored-procedures sql-server-2012