Case 语句变量声明和使用 IN MS SQL SERVER
Case Statement Variable Declaration and use IN MS SQL SERVER
我正在为我的 Shiny 应用程序使用 MySQL。
我正在为 App 使用此查询,它 运行 完全没问题。
Select
concat(monthname(date_of_test), '-', year(date_of_test)) as 'Time',
product_group AS 'ProductGroup',
Pass,
Case
when pass='N' then @no:=count(distinct serial_number)
when pass='Y' then count(distinct serial_number)-@no
end as Count
from test_data
where
year(date_of_test)=2018
and product_group='BHO'
and month(date_of_test) between 3 and 4
group by
product_group,
month(date_of_test),
pass
但我需要在 MS SQL 服务器中更改它。我尝试声明为变量并将其用作 SQL Server.
我在 SQL 服务器上的尝试:
declare @no int;
set @no = 0;
Select
CONCAT(datename(MM, date_of_test), '-', DATENAME(YY,date_of_test)) as 'Time',
product_group AS 'ProductGroup',
Pass,
case
when pass ='N' then @no = count(distinct serial_number)
when pass ='Y' then count(distinct serial_number)- @no
end as 'Count'
from test_data
where
year(date_of_test)=2018
and product_group='BHO'
and month(date_of_test) between 3 and 5
group by
product_group,
CONCAT(datename(MM, date_of_test),
'-',
DATENAME(YY,date_of_test)),
pass
没有变量的查询如下:
Select
CONCAT(datename(MM, date_of_test), '-', DATENAME(YY,date_of_test)) as 'Time',
product_group AS 'ProductGroup',
Pass,
case
when pass ='N' then count(distinct serial_number)
when pass ='Y' then count(distinct serial_number)
end as 'Count'
from test_data
where
year(date_of_test)=2018 and product_group='BHO'
and month(date_of_test) between 3 and 4
group by
product_group,
CONCAT(datename(MM, date_of_test),
'-',
DATENAME(YY,date_of_test)),
pass
它产生以下输出:
所需的输出类似于 MySQL。请看一下 Pass=Y 然后从中减去 Pass=N 的值。
显示错误。
我的初步假设:在 MySQL 中我可以在查询中初始化变量并可以在其中使用它,但在 MS SQL 服务器中可能还有其他规则。
我的语法或过程可能是错误的。
Select Count(distinct serial_number) from Test_Data where year(date_of_test)=2018 and product_group='BHO'and month(date_of_test)=4
503
Select Count(distinct serial_number) from Test_Data where year(date_of_test)=2018 and product_group='BHO' and PASS='Y' and month(date_of_test)=4
503
Select Count(distinct serial_number) from Test_Data where year(date_of_test)=2018 and product_group='BHO' and PASS='N'and month(date_of_test)=4
71
所以所有 503 个产品(序列号)都进行了多次测试并获得了 Pass=Y 值,但是 71 个产品已经通过了相同的测试,在某些情况下它们失败了,并被标记为 Pass=N。
因此,如果我可以计算 (distinct serial_number with PASS=y)-(distinct serial_number with PASS=N) 那么它将给出通过所有测试的产品数量。
我可以做到,结果是:
Select CONCAT(datename(MM, date_of_test),'-',DATENAME(YY,date_of_test)) as 'Time',product_group AS 'ProductGroup',
(Count(Distinct case when PASS='Y' then serial_number end)-Count(Distinct case when PASS='N' then serial_number end))
as ' All Test Passed',
Count(Distinct case when PASS='N' then serial_number end) as 'Min 1 Test Failed'
from test_data
where
year(date_of_test)=2018
and
month(date_of_test) between 3 and 4
and product_group='BHO'
group by product_group,CONCAT(datename(MM, date_of_test),'-',DATENAME(YY,date_of_test))
结果是
看起来 MySQL 查询正在尝试模拟 MySQL 8 中引入的 LEAD()
或 LAG()
分析函数。这些在 [=56= 中已经可用] 自 2012 年以来的服务器(我认为)。
MySQL 查询假定结果将按特定顺序 return 编辑,即使没有 ORDER BY 子句。它还假设没有并行处理,至少在处理变量时是这样。
整个CASE
可以重写为:
count(distinct serial_number) -
LAG(count(distinct serial_number),1,0) OVER (
PARTITION BY product_group,month
ORDER BY pass)
这会按 product_group,month
对 GROUP BY
结果进行分区,然后按 pass
对它们进行排序。 LAG
然后 returns 该分区中的 previous 计数,如果没有前一行则为 0。这意味着 LAG()
将 return 0 用于 N
并且 N 的计数用于 Y
完整的查询如下所示:
select
year(date_of_test),
month(date_of_test),
product_group,
pass,
count(distinct serial_number) -
LAG( COUNT(distinct serial_number),1,0)
OVER ( PARTITION BY product_group,month(date_of_test)
ORDER BY pass)
from test_data
where
year(date_of_test)=2018
and month(date_of_test) between 3 and 4
and product_group='BHO'
group by
year(date_of_test),
month(date_of_test),
product_group,
pass
类似的查询可以使用 MySQL 8.
性能和查询本身可以通过使用 a Calendar table 提高 很多。日历 table 是一个 table 预填充了例如 20 年的日期,其中包含额外的字段,例如月份、月份名称、周数、工作或假期等。这使得编写基于日期的查询变得很多更容易,结果查询更快。
假设有一个 calendar
table 只有几个基本字段,如日期、年、月、mont_name,可以将查询简化为:
select
calendar.month_name + '-' + calendar.year,
product_group,
pass,
count(distinct serial_number) -
LAG( COUNT(distinct serial_number),1,0)
OVER ( PARTITION BY product_group,calendar.month
ORDER BY pass)
from
test_data
inner join calendar on date_of_test=date
where
calendar.year =2018
and calendar.month between 3 and 4
and product_group='BHO'
group by
calendar.year,
calendar.month,
product_group,
pass
此查询可以利用 date_of_test
、calendar.date
、calendar.year
和 calendar.month
列上的索引来查找结果。
我正在为我的 Shiny 应用程序使用 MySQL。 我正在为 App 使用此查询,它 运行 完全没问题。
Select
concat(monthname(date_of_test), '-', year(date_of_test)) as 'Time',
product_group AS 'ProductGroup',
Pass,
Case
when pass='N' then @no:=count(distinct serial_number)
when pass='Y' then count(distinct serial_number)-@no
end as Count
from test_data
where
year(date_of_test)=2018
and product_group='BHO'
and month(date_of_test) between 3 and 4
group by
product_group,
month(date_of_test),
pass
但我需要在 MS SQL 服务器中更改它。我尝试声明为变量并将其用作 SQL Server.
我在 SQL 服务器上的尝试:
declare @no int;
set @no = 0;
Select
CONCAT(datename(MM, date_of_test), '-', DATENAME(YY,date_of_test)) as 'Time',
product_group AS 'ProductGroup',
Pass,
case
when pass ='N' then @no = count(distinct serial_number)
when pass ='Y' then count(distinct serial_number)- @no
end as 'Count'
from test_data
where
year(date_of_test)=2018
and product_group='BHO'
and month(date_of_test) between 3 and 5
group by
product_group,
CONCAT(datename(MM, date_of_test),
'-',
DATENAME(YY,date_of_test)),
pass
没有变量的查询如下:
Select
CONCAT(datename(MM, date_of_test), '-', DATENAME(YY,date_of_test)) as 'Time',
product_group AS 'ProductGroup',
Pass,
case
when pass ='N' then count(distinct serial_number)
when pass ='Y' then count(distinct serial_number)
end as 'Count'
from test_data
where
year(date_of_test)=2018 and product_group='BHO'
and month(date_of_test) between 3 and 4
group by
product_group,
CONCAT(datename(MM, date_of_test),
'-',
DATENAME(YY,date_of_test)),
pass
它产生以下输出:
所需的输出类似于 MySQL。请看一下 Pass=Y 然后从中减去 Pass=N 的值。
显示错误。
我的初步假设:在 MySQL 中我可以在查询中初始化变量并可以在其中使用它,但在 MS SQL 服务器中可能还有其他规则。 我的语法或过程可能是错误的。
Select Count(distinct serial_number) from Test_Data where year(date_of_test)=2018 and product_group='BHO'and month(date_of_test)=4
503
Select Count(distinct serial_number) from Test_Data where year(date_of_test)=2018 and product_group='BHO' and PASS='Y' and month(date_of_test)=4
503
Select Count(distinct serial_number) from Test_Data where year(date_of_test)=2018 and product_group='BHO' and PASS='N'and month(date_of_test)=4
71
所以所有 503 个产品(序列号)都进行了多次测试并获得了 Pass=Y 值,但是 71 个产品已经通过了相同的测试,在某些情况下它们失败了,并被标记为 Pass=N。 因此,如果我可以计算 (distinct serial_number with PASS=y)-(distinct serial_number with PASS=N) 那么它将给出通过所有测试的产品数量。
我可以做到,结果是:
Select CONCAT(datename(MM, date_of_test),'-',DATENAME(YY,date_of_test)) as 'Time',product_group AS 'ProductGroup',
(Count(Distinct case when PASS='Y' then serial_number end)-Count(Distinct case when PASS='N' then serial_number end))
as ' All Test Passed',
Count(Distinct case when PASS='N' then serial_number end) as 'Min 1 Test Failed'
from test_data
where
year(date_of_test)=2018
and
month(date_of_test) between 3 and 4
and product_group='BHO'
group by product_group,CONCAT(datename(MM, date_of_test),'-',DATENAME(YY,date_of_test))
结果是
看起来 MySQL 查询正在尝试模拟 MySQL 8 中引入的 LEAD()
或 LAG()
分析函数。这些在 [=56= 中已经可用] 自 2012 年以来的服务器(我认为)。
MySQL 查询假定结果将按特定顺序 return 编辑,即使没有 ORDER BY 子句。它还假设没有并行处理,至少在处理变量时是这样。
整个CASE
可以重写为:
count(distinct serial_number) -
LAG(count(distinct serial_number),1,0) OVER (
PARTITION BY product_group,month
ORDER BY pass)
这会按 product_group,month
对 GROUP BY
结果进行分区,然后按 pass
对它们进行排序。 LAG
然后 returns 该分区中的 previous 计数,如果没有前一行则为 0。这意味着 LAG()
将 return 0 用于 N
并且 N 的计数用于 Y
完整的查询如下所示:
select
year(date_of_test),
month(date_of_test),
product_group,
pass,
count(distinct serial_number) -
LAG( COUNT(distinct serial_number),1,0)
OVER ( PARTITION BY product_group,month(date_of_test)
ORDER BY pass)
from test_data
where
year(date_of_test)=2018
and month(date_of_test) between 3 and 4
and product_group='BHO'
group by
year(date_of_test),
month(date_of_test),
product_group,
pass
类似的查询可以使用 MySQL 8.
性能和查询本身可以通过使用 a Calendar table 提高 很多。日历 table 是一个 table 预填充了例如 20 年的日期,其中包含额外的字段,例如月份、月份名称、周数、工作或假期等。这使得编写基于日期的查询变得很多更容易,结果查询更快。
假设有一个 calendar
table 只有几个基本字段,如日期、年、月、mont_name,可以将查询简化为:
select
calendar.month_name + '-' + calendar.year,
product_group,
pass,
count(distinct serial_number) -
LAG( COUNT(distinct serial_number),1,0)
OVER ( PARTITION BY product_group,calendar.month
ORDER BY pass)
from
test_data
inner join calendar on date_of_test=date
where
calendar.year =2018
and calendar.month between 3 and 4
and product_group='BHO'
group by
calendar.year,
calendar.month,
product_group,
pass
此查询可以利用 date_of_test
、calendar.date
、calendar.year
和 calendar.month
列上的索引来查找结果。