如何在不同条件下计算 SQL 中的不同值?
How to count distinct values in SQL under different conditions?
我有一个如下所示的数据。我想计算产品总数并创建一个 table 来总结不同日期范围的计数。请参见下图作为示例。这是我的码头:
SELECT(
SELECT Count(DISTINCT Product) FROM Table1 WHERE Date BETWEEN '01/01/2017 AND
'01/15/2017,
SELECT Count(DISTINCT Product) FROM Table1 WHERE Date BETWEEN '01/16/2017 AND
'01/31/2017,
);
但是我得到一个错误:
Incorrect syntax near ','
这会起作用
SELECT
(SELECT Count(DISTINCT Product) FROM Table1 WHERE Date BETWEEN '01/01/2017' AND
'01/15/2017'),
(SELECT Count(DISTINCT Product) FROM Table1 WHERE Date BETWEEN '01/16/2017' AND
'01/31/2017')
;
您的 SQL:
中存在一些语法错误
- 使用 BETWEEN 语句时,只能用引号引起来
每个日期。不要在引号中包含 AND。
- 您需要将每个内部 SELECTS 括起来。
- 末尾(右括号前)多了一个逗号
但是,此查询不会 return 值 5 和 2,因为您在每个 SELECT 中都指定了 DISTINCT。这只会给你 3 和 2,因为 Product (A/D/E) returned 从第一个查询中只有 3 个不同的值。如果您想要行数,请删除不同的。
最后,我建议您在 SQL 中使用日期文字时使用 YYYY-MM-DD 语法。这消除了关于日期和月份的任何歧义。例如,1/4/2017 可能是 1 月 4 日或 4 月 1 日,具体取决于 SQL 服务器的配置方式。如果您指定 2017-04-01,那么这将始终被解释为 4 月 1 日,而 2017-01-04 将始终是 1 月 4 日。
简单:
SELECT
(SELECT COUNT(DISTINCT Product) FROM yourtable T1 WHERE Date BETWEEN '01/01/2017' AND '01/15/2017') C1,
(SELECT COUNT(DISTINCT Product) FROM yourtable T2 WHERE Date BETWEEN '01/16/2017' AND '01/31/201') C2
输出:3 | 2
SELECT
(SELECT COUNT(*) FROM yourtable T1 WHERE Date BETWEEN '01/01/2017' AND '01/15/2017') C1,
(SELECT COUNT(*) FROM yourtable T2 WHERE Date BETWEEN '01/16/2017' AND '01/31/201') C2
输出:5 | 2
如果最后的代码不起作用,您需要使用 Convert and Cast:
Declare @tb table(product varchar(50),[Date] date)
insert into @tb
select 'A' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),4,2) as date) as [Date] union all
select 'A' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),4,2)as date) as [Date] union all
select 'D' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/5/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/5/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/5/2017' as date),110),4,2) as date) as [Date] union all
select 'E' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/6/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/6/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/6/2017' as date),110),4,2)as date) as [Date] union all
select 'E' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/10/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/10/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/10/2017' as date),110),4,2)as date) as [Date] union all
select 'D' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/25/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/25/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/25/2017' as date),110),4,2)as date) as [Date] union all
select 'A' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/30/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/30/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/30/2017' as date),110),4,2)as date) as [Date]
--Copy from here
select acnt as 'Count(01/01/2017-01/15/2017)',bcnt as 'Count(01/16/2017-01/31/2017)' from
(select count(1) as acnt from @tb where [Date] BETWEEN '01/01/2017' AND '01/15/2017') as a
left join
(select count(1) as bcnt from @tb where [Date] BETWEEN '01/16/2017' AND '01/31/2017') as b
On a.acnt != b.bcnt or a.acnt = b.bcnt
;WITH CTE(Product ,[Date])
As
(
SELECT 'A','1/1/2017' Union all
SELECT 'A','1/1/2017' Union all
SELECT 'D','1/5/2017' Union all
SELECT 'E','1/6/2017' Union all
SELECT 'E','1/10/2017' Union all
SELECT 'D','1/25/2017' Union all
SELECT 'A','1/30/2017'
)
SELECT SUM([Count Of between '1/1/2017' AND '1/15/2017']) AS [Count Of between (1/1/2017 AND 1/15/2017)]
,SUM([Count Of between '1/16/2017' AND '1/31/2017']) AS [Count Of between (1/16/2017 AND 1/31/2017)]
FROM (
SELECT COUNT(Product) OVER (
PARTITION BY [Date] ORDER BY Product
) AS [Count Of between '1/1/2017' AND '1/15/2017']
,ISNULL(NULL, '') AS [Count Of between '1/16/2017' AND '1/31/2017']
FROM cte
WHERE [Date] BETWEEN '1/1/2017'
AND '1/15/2017'
UNION ALL
SELECT ISNULL(NULL, '')
,COUNT(Product) OVER (
PARTITION BY [Date] ORDER BY Product
) AS [Count Of between '1/16/2017' AND '1/31/2017']
FROM cte
WHERE [Date] BETWEEN '1/16/2017'
AND '1/31/2017'
) Dt
输出
Count Of between (1/1/2017 AND 1/15/2017) | Count Of between (1/16/2017 AND 1/31/2017)
--------------------------------------------------------------------------------
5 2
我有一个如下所示的数据。我想计算产品总数并创建一个 table 来总结不同日期范围的计数。请参见下图作为示例。这是我的码头:
SELECT(
SELECT Count(DISTINCT Product) FROM Table1 WHERE Date BETWEEN '01/01/2017 AND
'01/15/2017,
SELECT Count(DISTINCT Product) FROM Table1 WHERE Date BETWEEN '01/16/2017 AND
'01/31/2017,
);
但是我得到一个错误:
Incorrect syntax near ','
这会起作用
SELECT
(SELECT Count(DISTINCT Product) FROM Table1 WHERE Date BETWEEN '01/01/2017' AND
'01/15/2017'),
(SELECT Count(DISTINCT Product) FROM Table1 WHERE Date BETWEEN '01/16/2017' AND
'01/31/2017')
;
您的 SQL:
中存在一些语法错误- 使用 BETWEEN 语句时,只能用引号引起来 每个日期。不要在引号中包含 AND。
- 您需要将每个内部 SELECTS 括起来。
- 末尾(右括号前)多了一个逗号
但是,此查询不会 return 值 5 和 2,因为您在每个 SELECT 中都指定了 DISTINCT。这只会给你 3 和 2,因为 Product (A/D/E) returned 从第一个查询中只有 3 个不同的值。如果您想要行数,请删除不同的。
最后,我建议您在 SQL 中使用日期文字时使用 YYYY-MM-DD 语法。这消除了关于日期和月份的任何歧义。例如,1/4/2017 可能是 1 月 4 日或 4 月 1 日,具体取决于 SQL 服务器的配置方式。如果您指定 2017-04-01,那么这将始终被解释为 4 月 1 日,而 2017-01-04 将始终是 1 月 4 日。
简单:
SELECT
(SELECT COUNT(DISTINCT Product) FROM yourtable T1 WHERE Date BETWEEN '01/01/2017' AND '01/15/2017') C1,
(SELECT COUNT(DISTINCT Product) FROM yourtable T2 WHERE Date BETWEEN '01/16/2017' AND '01/31/201') C2
输出:3 | 2
SELECT
(SELECT COUNT(*) FROM yourtable T1 WHERE Date BETWEEN '01/01/2017' AND '01/15/2017') C1,
(SELECT COUNT(*) FROM yourtable T2 WHERE Date BETWEEN '01/16/2017' AND '01/31/201') C2
输出:5 | 2
如果最后的代码不起作用,您需要使用 Convert and Cast:
Declare @tb table(product varchar(50),[Date] date)
insert into @tb
select 'A' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),4,2) as date) as [Date] union all
select 'A' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/1/2017' as date),110),4,2)as date) as [Date] union all
select 'D' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/5/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/5/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/5/2017' as date),110),4,2) as date) as [Date] union all
select 'E' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/6/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/6/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/6/2017' as date),110),4,2)as date) as [Date] union all
select 'E' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/10/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/10/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/10/2017' as date),110),4,2)as date) as [Date] union all
select 'D' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/25/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/25/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/25/2017' as date),110),4,2)as date) as [Date] union all
select 'A' as Product, cast(substring(CONVERT(VARCHAR(10), cast('1/30/2017' as date),110),7,4) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/30/2017' as date),110),1,2) + '-' +
substring(CONVERT(VARCHAR(10), cast('1/30/2017' as date),110),4,2)as date) as [Date]
--Copy from here
select acnt as 'Count(01/01/2017-01/15/2017)',bcnt as 'Count(01/16/2017-01/31/2017)' from
(select count(1) as acnt from @tb where [Date] BETWEEN '01/01/2017' AND '01/15/2017') as a
left join
(select count(1) as bcnt from @tb where [Date] BETWEEN '01/16/2017' AND '01/31/2017') as b
On a.acnt != b.bcnt or a.acnt = b.bcnt
;WITH CTE(Product ,[Date])
As
(
SELECT 'A','1/1/2017' Union all
SELECT 'A','1/1/2017' Union all
SELECT 'D','1/5/2017' Union all
SELECT 'E','1/6/2017' Union all
SELECT 'E','1/10/2017' Union all
SELECT 'D','1/25/2017' Union all
SELECT 'A','1/30/2017'
)
SELECT SUM([Count Of between '1/1/2017' AND '1/15/2017']) AS [Count Of between (1/1/2017 AND 1/15/2017)]
,SUM([Count Of between '1/16/2017' AND '1/31/2017']) AS [Count Of between (1/16/2017 AND 1/31/2017)]
FROM (
SELECT COUNT(Product) OVER (
PARTITION BY [Date] ORDER BY Product
) AS [Count Of between '1/1/2017' AND '1/15/2017']
,ISNULL(NULL, '') AS [Count Of between '1/16/2017' AND '1/31/2017']
FROM cte
WHERE [Date] BETWEEN '1/1/2017'
AND '1/15/2017'
UNION ALL
SELECT ISNULL(NULL, '')
,COUNT(Product) OVER (
PARTITION BY [Date] ORDER BY Product
) AS [Count Of between '1/16/2017' AND '1/31/2017']
FROM cte
WHERE [Date] BETWEEN '1/16/2017'
AND '1/31/2017'
) Dt
输出
Count Of between (1/1/2017 AND 1/15/2017) | Count Of between (1/16/2017 AND 1/31/2017)
--------------------------------------------------------------------------------
5 2