如何简化选择查询

Posted

技术标签:

【中文标题】如何简化选择查询【英文标题】:how to simplify the selection query 【发布时间】:2019-02-13 04:01:36 【问题描述】:

我必须在存储过程中选择如下查询。

SELECT @licenseCount = COUNT(*)  FROM ServicePool SP
INNER JOIN UserPackages UP ON UP.ServicePoolId = SP.Id 
    AND SP.UserId = UP.UserId
INNER JOIN Package P ON P.Id = UP.PackageId
LEFT OUTER JOIN CompanyProfile C ON C.LicenseId = SP.Id         
INNER JOIN CompanyProfile CP ON CP.CurrencyId = P.CurrencyId    
INNER JOIN PackageCategory PC ON PC.OrganizationTypeId = CP.OrganisationType 
    AND PC.PackageId = P.Id     
WHERE SP.Active = 1  
    AND SP.UserId = @uId 
    AND P.Active = 1  
    and CP.CompanyID = @cId
    and ISNULL(C.CompanyID,0) = 0 
    AND DATEDIFF(DAY,GETDATE(),DATEADD(DAY,P.ValidityPeriod,UP.PurchaseDate)) > 0 



SELECT @paymentCount = COUNT(*)  FROM ServicePool SP
INNER JOIN UserPackages UP ON UP.ServicePoolId=SP.Id 
    AND SP.UserId = UP.UserId
INNER JOIN Package P ON P.Id = UP.PackageId
LEFT OUTER JOIN CompanyProfile C ON C.LicenseId = SP.Id         
INNER JOIN CompanyProfile CP ON CP.CurrencyId = P.CurrencyId    
INNER JOIN PackageCategory PC ON PC.OrganizationTypeId = CP.OrganisationType 
    AND PC.PackageId = P.Id         
WHERE SP.Active = 1 
    AND SP.UserId = @uId 
    AND P.Active = 1  
    and CP.CompanyID = @cId
    and ISNULL(C.CompanyID,0) = 0 
    AND DATEDIFF(DAY,GETDATE(),DATEADD(DAY,P.ValidityPeriod,UP.PurchaseDate)) > 0 
    AND UP.PaymentStatus = 'P'

如您所见,上述两个选择查询之间的唯一区别是,在第二个查询的末尾,有一个额外的 where 条件,AND UP.PaymentStatus = 'P'

所以我想知道有什么方法可以简化这些查询吗?

【问题讨论】:

“简化”是什么意思?你也会有重复的数据......为什么第一个没有:AND UP.PaymentStatus <> 'P' UP.PaymentStatus 可以是W or P,在任何一种情况下都需要在第一个条件下取值,只有在UP.PaymentStatus = P 时才能在第二个条件下取值 【参考方案1】:

下面是查询

SELECT @licenseCount = COUNT(*), @paymentCount = COUNT(case when UP.PaymentStatus = 'P' then 1 else 0 end)   FROM ServicePool SP
    INNER JOIN UserPackages UP ON UP.ServicePoolId = SP.Id 
        AND SP.UserId = UP.UserId
    INNER JOIN Package P ON P.Id = UP.PackageId
    LEFT OUTER JOIN CompanyProfile C ON C.LicenseId = SP.Id         
    INNER JOIN CompanyProfile CP ON CP.CurrencyId = P.CurrencyId    
    INNER JOIN PackageCategory PC ON PC.OrganizationTypeId = CP.OrganisationType 
        AND PC.PackageId = P.Id     
    WHERE SP.Active = 1  
        AND SP.UserId = @uId 
        AND P.Active = 1  
        and CP.CompanyID = @cId
        and ISNULL(C.CompanyID,0) = 0 
        AND 
DATEDIFF(DAY,GETDATE(),DATEADD(DAY,P.ValidityPeriod,UP.PurchaseDate))

您可以在第一个查询本身中定义@paymentCount 变量

测试结果 -

hive> select * from test_so_t1;
OK
123     90001   90001
123     90001   90002
123     90001   90003
123     90002   90001
123     90002   90002
123     90003   90002
123     90003   90003
Time taken: 0.118 seconds, Fetched: 7 row(s)
hive> select count(case when mem_id=90001 then 1 else 0 end) as groupBy, group_id from test_so_t1 group by group_id;
Total MapReduce CPU Time Spent: 3 seconds 900 msec
OK
7       123
Time taken: 17.271 seconds, Fetched: 1 row(s)

【讨论】:

在你的回答中@paymentCount 只返回 1 或 0,但我需要 count(*) 不应该是这种情况,只有当 Payment_status='P' 的记录数为 1 或 0 时,您才会得到 1... 或者问题可能与您查询更新我的答案有关测试结果,

以上是关于如何简化选择查询的主要内容,如果未能解决你的问题,请参考以下文章

Laravel - 使用 Eloquent 查询构建器在选择中添加自定义列

如何从 x 等于多个值的地方进行选择?

Django:查询时显示选择“详细”名称(并且选择在相关模型中)

简化选择范围C#

使用这些临时表返回选择查询的临时表创建函数

tsql:在连接中选择子查询的替代方法