sql查询效率

时间:2014-12-15 15:58:28

标签: sql tsql

我有一个表定义如下:

CREATE TABLE [dbo].[ListingStats](
    [ListingStatID] [int] IDENTITY(1,1) NOT NULL,
    [StatTypeID] [int] NOT NULL,
    [CreatedDate] [date] NOT NULL,
    [ListingID] [int] NOT NULL,
    CONSTRAINT [PK_ListingStats] PRIMARY KEY CLUSTERED 
(
[ListingStatID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
       ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

我想为今天,过去7天,过去30天和所有时间获得每种类型(listingStatTypeID)的4个总计。

我不确定最有效的查询是什么。现在我有以下内容,我可以为每个TYPE重复,但这将是一个大查询,它将是很多电话。

declare @listingID int
set @listingID = 209722
--today
select count(1) from ListingStats where listingid = @listingid and CreatedDate = getdate()
--last 7 days
select count(1) from ListingStats where listingid = @listingid and CreatedDate > getdate()-7
--last 30 days
select count(1) from ListingStats where listingid = @listingid and CreatedDate > getdate()-30 
--all time
select count(1) from ListingStats where listingid = @listingid

我总是通过提供一个listingID来一次调用一个列表。 如果有人能提供方向我会很感激。我应该创建某种视图吗?

预期结果

-Type------Today-----7Days---30Days---Ever
  1         44        50       500    5000
  2         22        40       90     1000
  3         55        55       555    5555 

2 个答案:

答案 0 :(得分:2)

对于单个列表,您可以使用CASE表达式在单个查询中获取四个值:

SELECT SUM(CASE WHEN CreatedDate = getdate()    THEN 1 ELSE 0 END) AS v_today,
       SUM(CASE WHEN CreatedDate > getdate()-7  THEN 1 ELSE 0 END) AS v_week,
       SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
       COUNT(*) AS v_alltime
  FROM ListingStats
 WHERE listingid = @listingid

对于所有商家信息ID,

SELECT ListingID,
       SUM(CASE WHEN CreatedDate = getdate()    THEN 1 ELSE 0 END) AS v_today,
       SUM(CASE WHEN CreatedDate > getdate()-7  THEN 1 ELSE 0 END) AS v_week,
       SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
       COUNT(*) AS v_alltime
  FROM ListingStats
 GROUP BY ListingID

如果要获取每个StatTypeID的摘要(在一个ListingID中),那么:

SELECT ListingID,
       StatTypeID,
       SUM(CASE WHEN CreatedDate = getdate()    THEN 1 ELSE 0 END) AS v_today,
       SUM(CASE WHEN CreatedDate > getdate()-7  THEN 1 ELSE 0 END) AS v_week,
       SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
       COUNT(*) AS v_alltime
  FROM ListingStats
 GROUP BY ListingID, StatTypeID

如果您希望StatTypeID的摘要跨所有ListingID,则:

SELECT StatTypeID,
       SUM(CASE WHEN CreatedDate = getdate()    THEN 1 ELSE 0 END) AS v_today,
       SUM(CASE WHEN CreatedDate > getdate()-7  THEN 1 ELSE 0 END) AS v_week,
       SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
       COUNT(*) AS v_alltime
  FROM ListingStats
 GROUP BY StatTypeID

根据已添加的“预期结果”部分判断,此最后一个查询最接近您的需求。从评论来看,如果你想通过StatTypeID获得特定的ListingID的摘要,那么:

SELECT StatTypeID,
       SUM(CASE WHEN CreatedDate = getdate()    THEN 1 ELSE 0 END) AS v_today,
       SUM(CASE WHEN CreatedDate > getdate()-7  THEN 1 ELSE 0 END) AS v_week,
       SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
       COUNT(*) AS v_alltime
  FROM ListingStats
 WHERE ListingID = @listingid
 GROUP BY StatTypeID

如果您的getdate()函数调用存在问题(正如Gordon Linoffanswer所建议的那样),您还需要修复这些问题。

答案 1 :(得分:1)

您可以使用条件聚合执行此操作。这会将值分为四列:

select sum(case when CreatedDate = cast(getdate() as date) then 1 else 0 end) as today,
       sum(case when CreatedDate > cast(getdate() - 7 as date) then 1 else 0 end) as lastweek,
       sum(case when CreatedDate > cast(getdate() - 30 as date) then 1 else 0 end) as last30,
       count(*) as ever  
from ListingStats
where listingid = @listingid;

请注意getdate()返回datetime,带有时间组件(尽管名称不同),因此此查询会将值转换为日期(删除时间组件)。

要获取所有列表ID的信息:

select sum(case when CreatedDate = cast(getdate() as date) then 1 else 0 end) as today,
       sum(case when CreatedDate > cast(getdate() - 7 as date) then 1 else 0 end) as lastweek,
       sum(case when CreatedDate > cast(getdate() - 30 as date) then 1 else 0 end) as last30,
       count(*) as ever  
from ListingStats
group by listingid;