Sql 帮助跨多个列执行复杂的自引用查询
我在处理一个复杂的问题时遇到了困难 我查询的表有3列,ClientID int Not Null,ProductID int Not Null和expireydate smalldatetime Null 给定两个客户端ID的主数据集和合并数据集,我需要执行以下业务逻辑以返回单个数据集: 选择具有较大值的ClientID 产品的到期日期,其中 两个clientId的日期都不为空 选择到期日为空的ClientID 产品的有效期为一个月的日期 null,另一个不为null 选择产品的主ID 两个到期日均为空或 两个有效期相同 我尝试了以下方法,但被卡住了Sql 帮助跨多个列执行复杂的自引用查询,sql,sql-server,sql-server-7,Sql,Sql Server,Sql Server 7,我在处理一个复杂的问题时遇到了困难 我查询的表有3列,ClientID int Not Null,ProductID int Not Null和expireydate smalldatetime Null 给定两个客户端ID的主数据集和合并数据集,我需要执行以下业务逻辑以返回单个数据集: 选择具有较大值的ClientID 产品的到期日期,其中 两个clientId的日期都不为空 选择到期日为空的ClientID 产品的有效期为一个月的日期 null,另一个不为null 选择产品的主ID 两个到期
Create Table #ProductSub (ClientID int NOT NULL,
ProductID int NOT NULL,
ExpiryDate smalldatetime)
/* In real life there is a Clustered Primary Key On ClientID and ProductID
Load Up Some Test Data */
Insert into #ProductSub Values (1, 100, null)
Insert into #ProductSub Values (2, 100, null)
Insert into #ProductSub Values (1, 101, null)
Insert into #ProductSub Values (2, 102, null)
Insert into #ProductSub Values (1, 200, null)
Insert into #ProductSub Values (2, 200, '2009-01-01')
Insert into #ProductSub Values (1, 300, '2009-01-01')
Insert into #ProductSub Values (2, 300, null)
Insert into #ProductSub Values (1, 400, '2009-01-01')
Insert into #ProductSub Values (2, 400, '2008-01-01')
Insert into #ProductSub Values (1, 500, '2008-01-01')
Insert into #ProductSub Values (2, 500, '2009-01-01')
Insert into #ProductSub Values (1, 600, '2009-01-01')
Insert into #ProductSub Values (2, 600, '2009-01-01')
--Select * from #ProductSub
Declare @MasterClient int,
@ConsolClient int
Select @MasterClient = 1, @ConsolClient = 2
Select * from #ProductSub t1
/* Use Master Client ID When Expiry Date is Null) */
Where (ClientID = @MasterClient and ExpiryDate is null)
/* Use Consol ClientID if Expiry Date is null nut Expiry Date for Master Client ID is not */
OR (ClientID = @ConsolClient and ExpiryDate is null and ProductID not in (
Select ProductID from #ProductSub t2
Where (ClientID = @MasterClient and ExpiryDate is null))
)
OR -- OH NO my head exploded
/* OR EXISTS (Select 1
from #ProductSub t3
)*/
Drop Table #ProductSub
/********** Expected Output ************************
ClientID ProductID ExpiryDate
1 100 NULL
1 101 NULL
2 102 NULL
1 200 NULL
2 300 NULL
1 400 2009-01-01 00:00:00
2 500 2009-01-01 00:00:00
1 600 2009-01-01 00:00:00
非常感谢您的帮助
编辑:虽然听起来像是这样,但这不是家庭作业,而是一个现实生活中的问题,我希望找到一个现实生活中的解决方案,我可以自己解决,但我所有的解决方案都指向临时表。我应该指出,生产环境是SQLServer7 这里,我将条件移动到子查询。子查询连接Console和Master的行,因此您可以从这两行访问列。条件仍然有点复杂,因为可能缺少任何一行
select ps.*
from @ProductSub ps
inner join (
select
CASE
WHEN c.ClientID is null THEN m.ClientID
WHEN m.ClientID is null THEN c.ClientID
WHEN m.ExpiryDate is not null and c.ExpiryDate is not null THEN
CASE
WHEN c.ExpiryDate > m.ExpiryDate THEN c.ClientID
ELSE m.ClientID
END
WHEN m.ExpiryDate is null THEN m.ClientID
WHEN c.ExpiryDate is null THEN c.ClientID
ELSE m.ClientID
END as ClientId,
COALESCE(m.ProductId, c.ProductId) as ProductId
from @ProductSub m
full outer join @ProductSub c
on m.ProductID = c.ProductID
and m.ClientID <> c.ClientID
where IsNull(m.clientid,@MasterClient) = @MasterClient
and IsNull(c.clientid,@ConsolClient) = @ConsolClient
) filter
on filter.clientid = ps.clientid
and filter.productid = ps.productid
order by ps.ProductId
这里,我将条件移动到一个子查询。子查询连接Console和Master的行,因此您可以从这两行访问列。条件仍然有点复杂,因为可能缺少任何一行
select ps.*
from @ProductSub ps
inner join (
select
CASE
WHEN c.ClientID is null THEN m.ClientID
WHEN m.ClientID is null THEN c.ClientID
WHEN m.ExpiryDate is not null and c.ExpiryDate is not null THEN
CASE
WHEN c.ExpiryDate > m.ExpiryDate THEN c.ClientID
ELSE m.ClientID
END
WHEN m.ExpiryDate is null THEN m.ClientID
WHEN c.ExpiryDate is null THEN c.ClientID
ELSE m.ClientID
END as ClientId,
COALESCE(m.ProductId, c.ProductId) as ProductId
from @ProductSub m
full outer join @ProductSub c
on m.ProductID = c.ProductID
and m.ClientID <> c.ClientID
where IsNull(m.clientid,@MasterClient) = @MasterClient
and IsNull(c.clientid,@ConsolClient) = @ConsolClient
) filter
on filter.clientid = ps.clientid
and filter.productid = ps.productid
order by ps.ProductId
这个问题并不清楚,但正如我所理解的,可能是这样的:
DECLARE @MasterExpiry smalldatetime, @ConsolExpiry smalldatetime
SELECT @MasterExpiry = ExpiryDate FROM #ProductSub WHERE ClientID = @MasterClient
SELECT @ConsolExpiry = ExpiryDate FROM #ProductSub WHERE ClientID = @ConsolClient
SELECT CASE
WHEN @MasterExpiry IS NULL AND @ConsolExpiry IS NULL THEN @MasterClient
WHEN @MasterExpiry IS NULL THEN @MasterClient
WHEN @ConsolExpiry IS NULL THEN @ConsolClient
WHEN @MasterExpiry >= @ConsolExpiry THEN @MasterClient
ELSE @ConsolClient END AS [Client]
如果需要行数据,则将其选择到变量中,然后执行单独的选择
这个问题并不清楚,但正如我所理解的,可能是这样的:
DECLARE @MasterExpiry smalldatetime, @ConsolExpiry smalldatetime
SELECT @MasterExpiry = ExpiryDate FROM #ProductSub WHERE ClientID = @MasterClient
SELECT @ConsolExpiry = ExpiryDate FROM #ProductSub WHERE ClientID = @ConsolClient
SELECT CASE
WHEN @MasterExpiry IS NULL AND @ConsolExpiry IS NULL THEN @MasterClient
WHEN @MasterExpiry IS NULL THEN @MasterClient
WHEN @ConsolExpiry IS NULL THEN @ConsolClient
WHEN @MasterExpiry >= @ConsolExpiry THEN @MasterClient
ELSE @ConsolClient END AS [Client]
如果需要行数据,则将其选择到变量中,然后执行单独的选择
我真的很难相信这三个问题不是家庭作业。也许我还不清楚。我是在一个查询之后,显然是在考虑子查询。不,这不是家庭作业,但不要真的在乎它是否被标记为suchI。我很难相信这3个问题不是家庭作业。也许我还不清楚。我是在一个查询之后,显然是在考虑子查询。不,这不是家庭作业,但不要真的在意它是否被标记为suchMany谢谢!!!比我要走的临时桌子路线要简洁得多!非常感谢!!!比我要走的临时桌子路线要简洁得多!