sql server中的多个OR子句
我的代码是这样的:有没有关于避免这么多或语句的想法? (sql server) 提前谢谢sql server中的多个OR子句,sql,sql-server,sql-server-2005,Sql,Sql Server,Sql Server 2005,我的代码是这样的:有没有关于避免这么多或语句的想法? (sql server) 提前谢谢 nionios函数DATEPART为您提供一个整数,该整数表示列的日期部分,而不包含时间部分。也许你可以比较一下 如果您运行的SQL Server 2008或更新版本中存在数据类型DATE,则可以更改为: WHERE CAST(DateSent AS DATE) IN ('2012-12-21','2012-12-27','2013-01-03','2013-02-27','2013-03-07','201
nionios函数
DATEPART
为您提供一个整数,该整数表示列的日期部分,而不包含时间部分。也许你可以比较一下
如果您运行的SQL Server 2008或更新版本中存在数据类型
DATE
,则可以更改为:
WHERE CAST(DateSent AS DATE) IN ('2012-12-21','2012-12-27','2013-01-03','2013-02-27','2013-03-07','2013-03-22)
如果在SQL Server 2005上(事实证明),您可以通过以下方式实现相同的功能:
WHERE DATEADD(dd, 0, DATEDIFF(dd, 0, DateSent)) IN
('2012-12-21','2012-12-27','2013-01-03','2013-02-27','2013-03-07','2013-03-22)
您可以通过在中选择日期并使用
:
SELECT ID, COUNT(distinct address)
FROM Table
WHERE cast(datesent as date) in ('2012-12-21', '2012-12-27', '2013-01-03',
'2013-02-27', '2013-03-01', '2013-03-07',
'2013-03-22'
) and . . .
GROUP BY ID
我还将查询修改为使用count(distinct)
而不是子查询。假设address
从不NULL
,结果应该是相同的。如果它可以是NULL
,并且您想计算它,那么您可以执行以下操作:
SELECT ID, COUNT(distinct address) +
max(case when address is null then 1 else 0 end)
规范的SQL解决方案是使用一个包含要测试的日期的表,并在表和日期表之间进行内部联接,只返回在日期表中具有匹配项的源行
有多种方法可以创建日期表:
- 您可以使用所需的值在数据库中创建一个实际表。如果需要对照同一组日期进行检查,则此选项非常有用
- 您可以在语句中创建一个临时表,并用所需的值填充它。只有在有几个日期值需要检查时才实用
- 可以将dates表作为表值参数传递给查询。仅在SQL Server 2008及更高版本中可用。如果日期列表是由客户端应用程序生成的,则此选项非常有用
Gordon的解决方案更好,如果你有少量的日期,而且代码也更简单
编辑
由于日期来自文本文件,因此应使用SSIS或T-SQL命令将文件导入表中,并加入表
批量插入更可取,因为您可以在同一批中组合批量插入和查询语句。大容量插入要求文件是一个简单的分隔文件,并且可以将文本数据转换为目标列的类型,而无需显式转换。大容量插入可以处理一些转换,但对于简单的作业来说,它可能会变得太麻烦
SSIS在导入数据时具有极大的灵活性,但它是另一种外部工具。SQL2005或之后
WITH Dates AS
(
SELECT '2012-12-21' AS DateToCheck
UNION SELECT '2012-12-27'
UNION SELECT '2013-01-03'
UNION SELECT '2013-02-27'
UNION SELECT '2013-03-01'
UNION SELECT '2013-03-07'
UNION SELECT '2013-03-22'
)
SELECT ID, COUNT(*) AS UNIQUE_USERS
FROM dbo.Table
INNER JOIN Dates ON CONVERT(Date, DateSent) = DateToCheck
GROUP BY ID
如果您将时间戳强制转换为日期,并且由于您的范围是完整的天数,从逻辑上讲,您可以在(…)中将其编码为单个,
:
如果您有一个大的表,您可以创建一个带有ID和日期的索引视图
CREATE VIEW VIEW_TABLE WITH SCHEMABINDING
AS
SELECT ID, CONVERT(DATE, DATESENT) DateSent
FROM TABLE
GO
CREATE NONCLUSTERED INDEX ixDateView
ON [VIEW_Table] (DateSent)
之后
您使用的是什么版本的SQL Server?为什么要减少ORs的数量?因为这会导致SQL难看、难以维护或优化?日期值从何而来?客户端,另一个查询?我使用SQL server 2005,因为正如Panagiotis Kanavos所说,这会导致难看的SQL,我喜欢对其进行优化客户端提供的日期值和.txt格式不会减少OR语句的绝对正确性,但是它会使或语句的组件体积减少一半。当你只需要做一个IN(…)时,为什么这个CTE和UNIONS会这样做?不幸的是,日期并不少,而且每次都会改变。日期从何而来?客户端、另一个查询或视图、用户数据?
...
SELECT Address, ID
FROM Table
WHERE CAST (DateSent AS DATE) IN ('2012-12-21', '2012-12-27', '2013-01-03', '2013-02-27', '2013-03-01', '2013-03-07', '2013-03-22')
...
CREATE VIEW VIEW_TABLE WITH SCHEMABINDING
AS
SELECT ID, CONVERT(DATE, DATESENT) DateSent
FROM TABLE
GO
CREATE NONCLUSTERED INDEX ixDateView
ON [VIEW_Table] (DateSent)
SELECT ID, COUNT(distinct address)
FROM View_Table WITH (NOEXPAND)
WHERE DateSent in (
'2012-12-21',
'2012-12-27',
'2013-01-03',
...)
GROUP BY ID
create table #dates (DateFrom datetime, DateTo datetime)
insert into #dates (DateFrom, DateTo) values
('2012-12-21 00:00:00', '2012-12-21 23:59:59')
, ('2012-12-27 00:00:00', '2012-12-27 23:59:59')
etc...
SELECT ID, COUNT(*) AS UNIQUE_USERS
FROM
(SELECT DISTINCT Address, ID
FROM [Table]
join #dates on [Table].DateSent between #dates.DateFrom and #dates.DateTo
) AS USERS
GROUP BY USERS.ID