sql server中的多个OR子句

时间:2013-07-10 13:05:17

标签: sql sql-server sql-server-2005

我的代码是这样的:关于避免这么多或陈述的任何想法? (sql server)

 SELECT ID, COUNT(*) AS UNIQUE_USERS 
FROM 
    (SELECT Address, ID 
        FROM Table
        WHERE 
        (DateSent between '2012-12-21 00:00:00' and '2012-12-21 23:59:59' or
        DateSent between '2012-12-27 00:00:00' and '2012-12-27 23:59:59' or
        DateSent between '2013-01-03 00:00:00' and '2013-01-03 23:59:59' or
            DateSent between '2013-02-27 00:00:00' and '2013-02-27 23:59:59' or
        DateSent between '2013-03-01 00:00:00' and '2013-03-01 23:59:59' or
        DateSent between '2013-03-07 00:00:00' and '2013-03-08 23:59:59' or 
        DateSent between '2013-03-22 00:00:00' and '2013-03-22 23:59:59' 
)AND
        GROUP BY Address, ID
    ) AS USERS
GROUP BY USERS.ID

提前致谢

nionios

8 个答案:

答案 0 :(得分:2)

您可以通过投射到某个日期并使用in

来实现
  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)

答案 1 :(得分:0)

DATEPART函数为您提供一个整数,表示列的日期部分,而不包含时间部分。也许你可以比较一下。

http://msdn.microsoft.com/en-us/library/ms186724.aspx#GetDateandTimeParts

答案 2 :(得分:0)

如果您运行的是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)

答案 3 :(得分:0)

规范SQL解决方案是使用包含要测试的日期的表,并在表和日期表之间执行内部联接,并仅返回在日期表中具有匹配项的源行。

您可以通过多种方式创建日期表:

  • 您可以使用所需的值在数据库中创建实际表。如果您需要检查同一组日期,则非常有用。
  • 您可以在语句中创建临时表,并使用所需的值填充它。只有在需要检查几个日期值时才有用。
  • 您可以将日期表作为表值参数传递给查询。仅适用于SQL Server 2008及更高版本。如果日期列表由客户端应用程序生成,则有用

如果你的日期很少,并且编码也更简单,那么戈登的解决方案会更好。

修改 由于日期来自文本文件,您应该使用SSIS或BULK INSERT T-SQL命令在表中导入文件并加入表。

BULK INSERT是首选,因为您可以在同一批次中同时组合BULK INSERT和查询语句。 BULK INSERT要求文件是一个简单的分隔文件,文本数据可以转换为目标列的类型,而无需显式转换。 BULK INSERT可以处理一些转换,但对于简单的工作来说可能会变得太麻烦。

SSIS在导入数据时具有很大的灵活性,但它可以使用YetAnotherExternalTool。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

如果您将时间戳转换为日期,并且由于您的范围是整天,从逻辑上讲,您可以将其编码为单个IN (...)

...
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') 
...

答案 6 :(得分:0)

如果你有大表,你可以创建一个带有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)

 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

答案 7 :(得分:0)

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