从 50 列中选择
Posted
技术标签:
【中文标题】从 50 列中选择【英文标题】:SELECT from 50 columns 【发布时间】:2019-05-13 04:19:59 【问题描述】:我有一个表,其中包含大约 50 列的许多列,其中包含代表用户在执行过程时所采取的步骤的日期时间数据
SELECT UserID, Intro_Req_DateTime, Intro_Onset_DateTime, Intro_Comp_DateTime, Info_Req_DateTime, Info_Onset_DateTime, Info_Comp_DateTime,
Start_Req_DateTime, Start_Onset_DateTime, Start_Comp_DateTime,
Check_Req_DateTime, Check_Onset_DateTime, Check_Comp_DateTime,
Validate_Req_DateTime, Validate_Onset_DateTime, Validate_Comp_DateTime,
....
FROM MyTable
我想查找用户在某个日期时间之后执行的步骤
示例我想查找用户 ABC 他在 2019 年 5 月 2 日 17:25:36 之后所做的第一步
我不能用 case 来检查这需要很长时间来编码
有更简单的方法吗?
附:感谢大家建议重新设计数据库。不是所有的数据库都可以重新设计,这个数据库是我们拥有的大型系统之一,它已经使用了 20 多年。重新设计是不可能的。
【问题讨论】:
有 50 个datetime
列告诉我你的数据库设计是错误的。相反,您应该有一个表,其中可能包含 3 个 datetime
列(req、onset、comp),然后是一个类型。就目前而言,我认为您别无选择,只能在 where
子句中添加 50 个条件 - 仍然使用剪切和粘贴不会花费那么长时间。
或者可能编写一个包含 50 个案例语句的 View/ITVF,这样您只需要编写一次。
我可能有一个 Event 表,然后是一些标志或参考表来指定类型。重新考虑你的布局。
正如其他人所说,您将从重新设计数据架构中受益。一个最小的设计将有一个包含四列的表:ProcedureNumber、StepNumber、UserID、DateTime。使用跨越前三列的复合主键,并为第四列使用日期时间数据类型。
感谢大家建议重新设计数据库。不是所有的数据库都可以重新设计,这个数据库是我们拥有的大型系统之一,它已经使用了 20 多年。重新设计是不可能的。
【参考方案1】:
您可以使用CROSS APPLY
取消透视值。 UNPIVOT
的语法比较麻烦。
实际的查询文本应该是相当易于管理的。无需复杂的CASE
语句。是的,您必须在查询文本中明确列出所有 50 个列名,这是不可避免的,但只会出现一次。
SELECT TOP(1)
A.StepName
,A.dt
FROM
MyTable
CROSS APPLY
(
VALUES
('Intro_Req', Intro_Req_DateTime)
,('Intro_Onset', Intro_Onset_DateTime)
,('Intro_Comp', Intro_Comp_DateTime)
.........
) AS A (StepName, dt)
WHERE
MyTable.UserID = 'ABC'
AND A.dt > '2019-05-02T17:25:36'
ORDER BY dt DESC;
另见How to unpivot columns using CROSS APPLY in SQL Server 2012
【讨论】:
【参考方案2】:最好的方法是使用您的操作类型和完成操作的日期时间来设计您的表格。然后你可以使用一个简单的 where 子句来找到你想要的。该表应如下表所示:
ID ActionType ActionDatetime
----------- ----------- -------------------
1492 1 2019-05-13 10:10:10
1494 2 2019-05-13 11:10:10
1496 3 2019-05-13 12:10:10
1498 4 2019-05-13 13:10:10
1500 5 2019-05-13 14:10:10
但在您当前的解决方案中,您应该使用 UNPIVOT 来获得您想要的。您可以在此LINK 中找到更多信息。
【讨论】:
以上是关于从 50 列中选择的主要内容,如果未能解决你的问题,请参考以下文章