我刚刚为报告撰写了此查询。但我最初在每个子查询中都没有使用日期范围过滤器编写它。但那没用。所以我将它添加到每个子查询中。这很有效,但我不是每次都要重复它,是否有语法来做同样的事情更简单?
SELECT Count(r.id) AS cnt_total,
(SELECT Count(r1.entity_id)
FROM auto_reminders_members r1
WHERE r1.reminder_id = r.reminder_id
AND r1.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013',
101)
AND
CONVERT(DATETIME,
'03/28/2013' + ' 23:59:59.997 ', 101)
AND r1.action = 'notnow') AS cnt_notnow,
(SELECT Count(r1.entity_id)
FROM auto_reminders_members r1
WHERE r1.reminder_id = r.reminder_id
AND r1.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013',
101)
AND
CONVERT(DATETIME,
'03/28/2013' + ' 23:59:59.997 ', 101)
AND r1.action = 'insert') AS cnt_insert,
(SELECT Count(r1.entity_id)
FROM auto_reminders_members r1
WHERE r1.reminder_id = r.reminder_id
AND r1.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013',
101)
AND
CONVERT(DATETIME,
'03/28/2013' + ' 23:59:59.997 ', 101)
AND r1.action = 'update') AS cnt_update,
(SELECT Count(r1.entity_id)
FROM auto_reminders_members r1
WHERE r1.reminder_id = r.reminder_id
AND r1.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013',
101)
AND
CONVERT(DATETIME,
'03/28/2013' + ' 23:59:59.997 ', 101)
AND r1.action = 'verify') AS cnt_verify
FROM auto_reminders_members r
WHERE r.reminder_id = 1
AND r.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013', 101) AND
CONVERT(DATETIME,
'03/28/2013' + ' 23:59:59.997 ', 101
)
GROUP BY r.reminder_id
答案 0 :(得分:11)
如果没有所有子查询
,这是一种方法SELECT Count(r.id) AS cnt_total,
sum(case when r.action = 'notnow' then 1 else 0 end) as 'cnt_notnow',
sum(case when r.action = 'insert' then 1 else 0 end) as 'cnt_insert',
sum(case when r.action = 'update' then 1 else 0 end) as 'cnt_update',
sum(case when r.action = 'verify' then 1 else 0 end) as 'cnt_verify'
FROM auto_reminders_members r
WHERE r.reminder_id = 1
AND CONVERT(DATE, r.date_last_reminder) = '20130328'
我还清理了一下查询,删除了组,因为这将始终为1,并更改日期比较以避免使用逻辑之间的混乱(感谢Aaron的评论)
答案 1 :(得分:2)
以下是使用GROUPING SETS
和PIVOT
的方法,但这取决于您使用的版本,您忘了告诉我们:
DECLARE @reminder_id INT, @date DATE;
SELECT @reminder_id = 1, @date = '20130328';
;WITH x AS
(
SELECT [action] = COALESCE([action],'Total'), c2 = COUNT(*)
FROM dbo.auto_reminders_members
WHERE reminder_id = @reminder_id
AND CONVERT(DATE, date_last_reminder) = @date
GROUP BY GROUPING SETS(([action]), ())
)
SELECT reminder_id = @reminder_id, * FROM x
PIVOT
(
MAX([c2]) FOR [action] IN ([Total],[notnow],[insert],[update],[verify])
) AS p;
如果是2005,您可以使用旧式语法替换GROUPING SETS
行:
GROUP BY [action] WITH ROLLUP
我真的希望人们不再容忍BETWEEN
和这个神奇的“日常结束”的东西。如果你想要一整天你的WHERE子句应该是:
WHERE CONVERT(DATE, r.date_last_reminder) = '20130328'
或者,如果您在2005年:
WHERE r.date_last_reminder >= '20130328'
AND r.date_last_reminder < '20130329'
这里有一些重点,主要是23:59:59.997
可能会根据基础数据类型对数据进行舍入或遗漏,没有理由将日期时间值转换为字符串来执行查询,以及像m/d/y
这样的区域格式由于各种原因而不好(例如,如果您的查询是03/08/2013
,我不知道您是在3月8日之后还是8月3日之后)。
请阅读这些文章:
您还应该注意为列名使用保留字/关键字,例如entity_id
和action
。
答案 2 :(得分:0)
你可能会做这样的事情
SELECT Count(r.id) AS cnt_total,
SUM(CASE WHEN r1.action = 'notnow') THEN 1 ELSE 0 END) AS cnt_notnow,
SUM(CASE WHEN r1.action = 'insert') THEN 1 ELSE 0 END) AS cnt_insert,
SUM(CASE WHEN r1.action = 'update') THEN 1 ELSE 0 END) AS cnt_update,
SUM(CASE WHEN r1.action = 'verify') THEN 1 ELSE 0 END) AS cnt_verify,
FROM auto_reminders_members r
WHERE r.reminder_id = 1
AND r.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013', 101) AND
CONVERT(DATETIME,
'03/28/2013' + ' 23:59:59.997 ', 101
)
GROUP BY r.reminder_id
答案 3 :(得分:0)
试试这个:
select
reminder_id,
count(1) as Total,
sum(case when r1.action = 'notnow' then 1 else 0 end) as cnt_notnow,
sum(case when r1.action = 'insert' then 1 else 0 end) as cnt_insert,
sum(case when r1.action = 'update' then 1 else 0 end) as cnt_update,
sum(case when r1.action = 'verify' then 1 else 0 end) as cnt_verify
from auto_reminders_members r
WHERE r.reminder_id = 1
AND r.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013', 101) AND
CONVERT(DATETIME,
'03/28/2013' + ' 23:59:59.997 ', 101
)
GROUP BY r.reminder_id
答案 4 :(得分:0)
找到一个替代解决方案:
SELECT Sum(1) AS cnt_total,
Sum(CASE
WHEN r.action = 'notnow' THEN 1
ELSE 0
END) AS cnt_notnow,
Sum(CASE
WHEN r.action = 'insert' THEN 1
ELSE 0
END) AS cnt_insert,
Sum(CASE
WHEN r.action = 'update' THEN 1
ELSE 0
END) AS cnt_update,
Sum(CASE
WHEN r.action = 'verify' THEN 1
ELSE 0
END) AS cnt_verify
FROM auto_reminders_members r 在哪里r.reminder_id = 1 AND r.date_last_reminder BETWEEN CONVERT(DATETIME,'03 / 28/2013',101)AND CONVERT(DATETIME, '03 / 28/2013'+ '23:59:59.997',101 )
答案 5 :(得分:0)
select convert(nvarchar(10),warnt.created_dt,120) 'Date',loc.loc_name 'Location',--
loctype.LocationTypeDesc,
(select SUM(stk.sel_price) from tbl_mst_stock as stk
inner join tbl_gen_warranty as wrn on stk.Stock_ID=wrn.Stock_Id
inner join tbl_mst_model as mdl on mdl.Model_ID=wrn.model_id
where wrn.mobile_type like 'SL')'Selleing Price',
(Select COUNT(stk.stk_code) from tbl_mst_stock as stk
inner join tbl_gen_warranty as warn on stk.Stock_ID=warn.Stock_Id
inner join tbl_mst_model mdl on mdl.Model_ID=warn.model_id
where warn.mobile_type like 'SL') 'Stock count'
From tbl_mst_location as loc
inner join tbl_mst_location_types loctype on loc.LocationTypeID=loctype.LocationTypeID
inner join tbl_gen_warranty as warnt on loc.Location_ID=warnt.Location_id
Where loctype.LocationTypeID=1 and loctype.group_id=1
and (CONVERT(nvarchar(10),warnt.created_dt,120)
Between CONVERT(nvarchar(10),'2013-01-01',120) and convert(nvarchar(10),'2013-07-09'))
Group by loc.loc_name,loctype.LocationTypeDesc,warnt.created_dt,loctype.LocationTypeID