我如何使用子查询来选择最大值?

问题描述 投票:1回答:2

Database

我正在尝试构造一个困难的SQL Server查询以选择特定数据。首先,让我给您一些背景信息...

我正在使用一个数据库,需要使用此查询访问3个表。您可以在图中看到该图。如您所见,此数据库中有用户。这些用户可以购买订阅,以在城市中使用一些公共自行车。订阅具有订阅类型。此订阅类型声明订阅有效的时间。可以是一天,一个月或一年。一个用户可以有多个订阅。

对于我的查询,我需要选择userId,名称,由街道,数字,邮政编码,城市和国家/地区代码组成的地址,以及订阅类型的描述。对于每个用户,我只需要最长的订阅时间。因此您必须在subscriptionTypeId DESC上过滤查询。不仅如此……一个用户可以拥有同一类型的多个订阅,因此我只需要最新的订阅即可。这意味着我还必须在订阅类型期间最长的时间上对ValidFrom DESC进行过滤。

我知道我需要为此使用子查询,但是似乎找不到合适的查询...这就是我所能走到的远,但是我一直在使用多种技术来尝试获得我所需要的:

SELECT 
    su.userId, u.name, u.street, u.number, u.zipcode, u.CountryCode, st.description, 
    MAX(su.validFrom) AS MaxValidFrom, 
    (SELECT MAX(SubscriptionTypeId) FROM dbo.Subscriptions 
     WHERE UserId = su.UserId) AS MaxSubscriptionTypeId
FROM 
    dbo.Users u 
INNER JOIN 
    dbo.Subscriptions su ON u.userId = su.userId
INNER JOIN 
    dbo.SubscriptionTypes st ON su.subscriptionTypeId = st.subscriptionTypeId
HAVING 
    su.SubscriptionTypeId = MAX(su.SubscriptionTypeId)
ORDER BY 
    su.UserId, MaxValidFrom DESC;

预先感谢您的帮助!

Joren

sql-server select subquery max
2个回答
0
投票

Joren,

尝试像这样的缩放器功能调用

CREATE FUNCTION MaxSubscriptionTypeID

(@UserId int)返回int如开始宣告@ID int从dbo中选择@ID = MAX(SubscriptionTypeId)WHERE UserId = @UserID-返回函数结果返回idnull(@ ID,0)

END转到

选择su.userId,u.name,u.street,u.number,u.zipcode,u.CountryCode,st.description,MAX(su.validFrom)AS MaxValidFrom,dbo.MaxSubscriptionTypeID(su.UserId)AS MaxSubscriptionTypeId从dbo.Users u内部联接dbo.Subscriptions su ON u.userId = su.userId内部联接dbo.SubscriptionTypes st on su.subscriptionTypeId = st.subscriptionTypeId拥有su.SubscriptionTypeId = MAX(su.SubscriptionTypeId)订购su.UserId,MaxValidFrom DESC;


0
投票

SQL可能会与内联子查询捆绑在一起,具体取决于功能和资源索引等。

我会避免使用自定义函数,因为查询计划几乎总是受到它的负面影响。

将其断开,将使您获得用户拥有的Max(SubscriptionTypeId),以及订阅该TypeId的用户的最新实例。

SELECT 
    u.userId, u.name, u.street, u.number, u.zipcode, u.CountryCode
    --,st.description 
    --,MAX(su.validFrom) AS MaxValidFrom, 
    --,(SELECT MAX(SubscriptionTypeId) FROM dbo.Subscriptions WHERE UserId = su.UserId) AS MaxSubscriptionTypeId
into #temp
FROM 
    dbo.Users u 
WHERE EXISTS (SELECT top 1 1 from dbo.Subscriptions i_su where i_su.UserId = u.UserId)
--Now you have a list of all who have at least 1 subscription inside a temp table.

Select u.*
    ,st.description
    ,su.ValidFrom
    ,su.SubscriptionTypeId
    --This function will return a "Rank" for each user (partition) in order of the "Order By" clause.
    ,ROW_NUMBER() OVER (partition by u.UserId order by SubscriptionTypeId DESC, ValidFrom DESC) as RowNo
into #temp2
FROM #temp u
INNER JOIN dbo.Subscriptions su
ON u.userId = su.userId
INNER JOIN dbo.SubscriptionTypes st
ON su.subscriptionTypeId = st.subscriptionTypeId

SELECT *
FROM #temp2
where RowNo = 1
-- RowNo 1 has the data you want based on the rank.

if (object_id('temptb..#temp') IS NOT NULL)
    DROP TABLE #temp
if (object_id('temptb..#temp2') IS NOT NULL)
    DROP TABLE #temp2
© www.soinside.com 2019 - 2024. All rights reserved.