如何缩短 T-SQL 中的 WHERE 子句
Posted
技术标签:
【中文标题】如何缩短 T-SQL 中的 WHERE 子句【英文标题】:How to shorten WHERE clause in T-SQL 【发布时间】:2021-12-27 13:53:14 【问题描述】:我正在 SQL Server 2019 中为我的数据库编写以下视图,它工作正常。我觉得我的WHERE
子句太长了,也许你写的更短的子句会满足我的需要。 WHERE
子句也可以很好地过滤视图。这似乎太新手了,因此任何高级解决方案都值得赞赏。
CREATE VIEW dbo.View1
AS
SELECT
Table1.QNO,
Table1.QRevNO,
Table1.QID,
Table1.LStatus AS Status,
Table1.StatusCode AS [Status Code],
CASE
WHEN Table1.IsProject = 1 THEN 'Goods'
WHEN Table1.IsProject = 2 THEN 'Services'
ELSE 'Project'
END AS [Product Type],
Table2.ProductGroup AS [Group],
Table2.TotalOfItem AS [Sales],
Table3.CompanyName AS [Customer]
FROM
dbo.Table1
INNER JOIN
dbo.Table2 ON Table1.QID = Table2.QID
INNER JOIN
dbo.Table3 ON Table3.CompanyID = Table1.CompanyID
WHERE
Table1.RevActivated = 1
AND ((DATEPART(YEAR, Table1.ORDate) = DATEPART(YEAR, GETDATE())
OR (DATEPART(YEAR, Table1.PIDate) = DATEPART(YEAR, GETDATE())
AND Table1.ORDate IS NULL)
OR (DATEPART(YEAR, Table1.PODate) = DATEPART(YEAR, GETDATE())
AND Table1.ORDate IS NULL
AND Table1.PIDate IS NULL)
OR (DATEPART(YEAR, Table1.BADate) = DATEPART(YEAR, GETDATE())
AND Table1.ORDate IS NULL
AND Table1.PIDate IS NULL
AND Table1.PODate IS NULL)
OR (DATEPART(YEAR, Table1.OCDate) = DATEPART(YEAR, GETDATE())
AND Table1.ORDate IS NULL
AND Table1.PIDate IS NULL
AND Table1.PODate IS NULL
AND Table1.BADate IS NULL)
OR (DATEPART(YEAR, Table1.ShipDate) = DATEPART(YEAR, GETDATE())
AND Table1.ORDate IS NULL
AND Table1.PIDate IS NULL
AND Table1.PODate IS NULL
AND Table1.BADate IS NULL
AND Table1.OCDate IS NULL)
OR (DATEPART(YEAR, Table1.INVDate) = DATEPART(YEAR, GETDATE())
AND Table1.ORDate IS NULL
AND Table1.PIDate IS NULL
AND Table1.PODate IS NULL
AND Table1.BADate IS NULL
AND Table1.OCDate IS NULL
AND Table1.ShipDate IS NULL)
OR (DATEPART(YEAR, Table1.PDDate) = DATEPART(YEAR, GETDATE())
AND Table1.ORDate IS NULL
AND Table1.PIDate IS NULL
AND Table1.PODate IS NULL
AND Table1.BADate IS NULL
AND Table1.OCDate IS NULL
AND Table1.ShipDate IS NULL
AND Table1.INVDate IS NULL)))
GO
【问题讨论】:
似乎你有一个非规范化问题:你不应该有七个相似的日期列,而是你想要一个单独的事件表(外键为Table1
),然后你可以做一个简单加入或exists
仅供参考,在WHERE
的列上使用DATEPART
之类的内容会导致您的查询不可搜索,从而导致性能下降。不是检查年份,而是检查日期是否在包含全年的日期范围内。例如>= '2021-01-01'
和< '2022-01'01'
。
【参考方案1】:
在 SQL 中,更紧凑的代码不一定是更好的代码。虽然以下内容可能更容易阅读:
...
WHERE t1.RevActivated = 1
and coalesce(
t1.ORDate,
t1.PIDate,
t1.PODate,
t1.BADate,
t1.OCDate,
t1.ShipDate,
t1.INVDate,
t1.PDDate
) >= datefromparts(year(getdate()), 1, 1)
and coalesce(
t1.ORDate,
t1.PIDate,
t1.PODate,
t1.BADate,
t1.OCDate,
t1.ShipDate,
t1.INVDate,
t1.PDDate
) < datefromparts(year(getdate()) + 1, 1, 1);
其中t1
是alias 的dbo.Table1
表。
即使在您的表格大小超过 Excel 电子表格支持的行数之后,要让这种混乱运行得足够快,这并不容易。您可以尝试使用包含所有 8 个 XyzDate
列的索引,其顺序与您的代码优先考虑它们的顺序完全相同。更好的方法是规范化您的数据模型,而不是使用数据源(当然,除非这不是 DWH)。
【讨论】:
以上是关于如何缩短 T-SQL 中的 WHERE 子句的主要内容,如果未能解决你的问题,请参考以下文章