sql server中的多个OR子句

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

我的代码是这样的:有没有关于避免这么多或语句的想法? (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','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