2

我的代码是这样的:关于避免这么多或语句的任何想法?(SQL服务器)

 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

提前致谢

尼奥尼奥斯

4

8 回答 8

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是 never NULL。如果可以NULL并且您想计算它,那么您可以这样做:

  SELECT ID, COUNT(distinct address) +
             max(case when address is null then 1 else 0 end)
于 2013-07-10T13:13:23.533 回答
0

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

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

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

如果您的日期数量较少,Gordon 的解决方案会更好,并且编码也更简单。

编辑 由于日期来自文本文件,您应该使用 SSIS 或BULK INSERT T-SQL 命令将文件导入表中并连接表。

BULK INSERT 更可取,因为您可以将 BULK INSERT 和查询语句组合在同一个批处理中。BULK INSERT 要求文件是简单的分隔文件,并且可以将文本数据转换为目标列的类型而无需显式转换。BULK INSERT 可以处理一些转换,但对于简单的工作可能会变得过于繁琐。

SSIS 在导入数据时提供了极大的灵活性,但它是 YetAnotherExternalTool 使用。

于 2013-07-10T13:16:04.430 回答
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
于 2013-07-10T13:17:30.810 回答
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') 
...
于 2013-07-10T13:18:06.833 回答
0

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

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

于 2013-07-10T13:10:20.647 回答
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
于 2013-07-10T13:23:36.573 回答
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
于 2013-07-10T13:28:37.020 回答
0

如果您正在运行DATE存在数据类型的 SQL Server 2008 或更高版本,您可以更改为:

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)
于 2013-07-10T13:13:13.103 回答