case语句变量声明及其在mssqlserver中的应用

t98cgbkg  于 2021-06-18  发布在  Mysql
关注(0)|答案(1)|浏览(365)

我正在使用mysql作为我闪亮的应用程序。我正在使用这个应用程序的查询,它运行完全正常。

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

但我需要在mssqlserver中更改它。我尝试过声明为变量,并在SQLServer中使用它。
我在sql server中的试用:

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中,我可以初始化查询中的变量并在其中使用它,但在mssqlserver中,可能还有其他规则。我的语法或过程可能是错误的。

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个产品(序列号)都进行了多次测试,并获得通过=y值,但71个产品通过了相同的测试,在某些情况下,它们失败了,在某些情况下,它被记为通过=n。因此,如果我能计算出(distinct serial\ U number with pass=y)-(distinct serial\ U 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))

结果是

pb3s4cty

pb3s4cty1#

看起来mysql查询正在尝试模拟 LEAD() 或者 LAG() mysql 8中引入的分析函数。自2012年以来,sql server就已经提供了这些功能(我想)。
mysql查询假设结果将按特定顺序返回,即使没有orderby子句。它还假设没有并行处理,至少在处理变量时是这样。
整个 CASE 可以重写为:

count(distinct serial_number) - 
LAG(count(distinct serial_number),1,0) OVER (
                        PARTITION BY product_group,month 
                        ORDER BY pass)

这使我们分道扬镳 GROUP BY 结果依据 product_group,month 然后命令他们 pass . LAG 然后返回该分区中的上一个计数,如果没有上一行,则返回0。这意味着 LAG() 将为返回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。
使用日历表可以大大提高性能和查询本身。日历表是一个预先填充了20年的日期的表,其中包含额外的字段,如月、月名、周数、工作或假日等。这使得编写基于日期的查询变得更容易,生成的查询也更快。
假设有一个 calendar 表中只有一些基本字段,如日期、年份、月份、月份名称,可以将查询简化为:

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 列以查找结果。

相关问题