我一直在桌子上敲打着试图弄清楚这个。我有一张表来存储工作信息,以及工作未完成的原因。原因是数字,01,02,03等。您可以将两个原因作为待处理作业。如果选择两个原因,它们将存储在同一列中,并以逗号分隔。这是 JOBID 表中的一个示例:
Job_Number User_Assigned PendingInfo
1 user1 01,02
还有另一个名为待定的表格,用于存储这些值实际代表的内容。 01 =信息不足,02 =时间不够,03 =等待审核。例如:
Pending_Num PendingWord
01 Not Enough Info
02 Not Enough Time
我要做的是查询数据库,以便为我提供所有工作号,用户,pendinginfo和待决理由。我可以突破第一个值,但无法弄清楚如何做第二个。到目前为止我的技能有限:
select Job_number,user_assigned,SUBSTRING(pendinginfo,0,3),pendingword
from jobid,pending
where
SUBSTRING(pendinginfo,0,3)=pending.pending_num and
pendinginfo!='00,00' and
pendinginfo!='NULL'
我想在这个例子中看到的是:
Job_Number User_Assigned PendingInfo PendingWord PendingInfo PendingWord
1 User1 01 Not Enough Info 02 Not Enough Time
提前致谢
答案 0 :(得分:5)
如果你的SQL想要单独处理它们,你真的不应该在一列中存储多个项目。在这些情况下你必须执行的“SQL体操”既丑陋又糟糕。
理想的解决方案是将单个项目拆分为单独的列,对于3NF,如果确实想要正确地执行此操作,则将这些列移动到单独的表中(但可能是婴儿步骤)好的,如果你确定短期中不会有两个以上的原因。)
然后您的查询将更简单,更快。
但是,如果这不是一个选项,你可以使用上述的SQL体操来做类似的事情:
where find ( ',' |fld| ',', ',02,' ) > 0
假设您的SQL方言具有字符串搜索功能(在这种情况下为find
,但我认为charindex
用于SQLServer)。
这将确保所有子列以逗号开头并以逗号(逗号加字段加逗号)开头,并查找特定的所需值(两边都有逗号以确保它是完整的子列匹配)。
如果无法控制应用程序在该列中放置的内容,我会选择DBA解决方案 - DBA解决方案被定义为DBA必须做的工作来解决他们的不足之处用户: - )。
在该表中创建两个新列并创建一个插入/更新触发器,该触发器将使用用户放入原始列的两个原因填充它们。
然后查询这两个 new 列以获取特定值,而不是尝试拆分旧列。
这意味着拆分成本仅适用于行插入/更新,而不是_every single select`,从而有效地分摊成本。
不过,我的答案是重新制作架构。从速度,可读查询和可维护性方面来看,这将是长期的最佳方式。
答案 1 :(得分:5)
我希望你只是维护代码,而不是一个全新的实现。
请考虑使用支持表使用不同的方法,如下所示:
JOBS TABLE
jobID | userID
--------------
1 | user13
2 | user32
3 | user44
--------------
PENDING TABLE
pendingID | pendingText
---------------------------
01 | Not Enough Info
02 | Not Enough Time
---------------------------
JOB_PENDING TABLE
jobID | pendingID
-----------------
1 | 01
1 | 02
2 | 01
3 | 03
3 | 01
-----------------
您可以使用JOIN或子查询轻松查询此表 如果您需要对软件进行复古兼容,则可以添加视图以实现此目标。
答案 2 :(得分:3)
我有一张表:
Events
---------
eventId int
eventTypeIds nvarchar(50)
...
EventTypes
--------------
eventTypeId
Description
...
每个事件都可以指定多个事件类型。
我所做的就是在我的站点代码中编写2个过程,而不是SQL代码
一个过程将表字段(eventTypeIds)值(如“3,4,15,6”)转换为ViewState数组,因此我可以在代码中的任何位置使用它。
此过程相反,它会收集您选中的所有选项并将其转换为
答案 3 :(得分:2)
如果更改架构是一个选项(它可能应该是),你不应该在这里实现多对多关系,这样你就可以在两个项目之间建立一个桥接表吗?这样,您可以将数字及其措辞存储在一个表中,将作业存储在另一个表中,并将“工作失败原因”存储在桥接表中......
答案 4 :(得分:1)
查看我回答here
的类似问题;WITH Numbers AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 0)) AS N
FROM JobId
),
Split AS
(
SELECT JOB_NUMBER, USER_ASSIGNED, SUBSTRING(PENDING_INFO, Numbers.N, CHARINDEX(',', PENDING_INFO + ',', Numbers.N) - Numbers.N) AS PENDING_NUM
FROM JobId
JOIN Numbers ON Numbers.N <= DATALENGTH(PENDING_INFO) + 1
AND SUBSTRING(',' + PENDING_INFO, Numbers.N, 1) = ','
)
SELECT *
FROM Split JOIN Pending ON Split.PENDING_NUM = Pending.PENDING_NUM
基本思想是你必须将每一行乘以与PENDING_NUM
一样多的次数。然后,提取字符串的适当部分
答案 5 :(得分:0)
虽然我同意DBA的观点,即不在单个字段中存储多个值,但对于应用程序逻辑和某些性能问题而言,它是可行的,如下所示。
假设您有10000个用户组,每个用户组平均有1000个成员。您可能希望有一个表user_groups,其中包含groupID和membersID等列。您的membersID列可以填充如下:
(',10,2001,20003,333,4520,')每个数字都是一个memberID,都用逗号分隔。在数据的开头和结尾添加逗号。然后你的选择将使用'%,someID,%'。
如果您无法更改数据('01,02,03')或类似数据,假设您想要包含01的行,您仍然可以使用“select ... LIKE '01,%'OR'%,01'或'% ,01,%'“这将确保它在开始,结束或内部匹配,同时避免相似的数字(即:101)。