SQL Left Join和Computed Column不能产生所需的结果

时间:2014-10-09 16:35:03

标签: sql join linq-to-sql calculated-columns

我相信我已离开这里,但我不确定最好的方法。我有产品表和预订表。我需要根据他们在特定时间范围内的预订,即时评估产品的可用性。每个产品可能有多个保留,但我的结果应该只是具有计算列的产品表,以确保其可用性。这是我到目前为止所做的,但左外连接不是我需要的。我确信我的案例陈述有更好的方法,并且取消了连接。

CREATE FUNCTION [dbo].[GetAvailableReservations]
(     
    @StartDate DateTime,
    @EndDate DateTime
)
RETURNS TABLE
AS
RETURN
(
    SELECT p.*, 
        CASE
            WHEN r.Status = 'Active' AND r.StartDate >= @StartDate AND r.EndDate <= @EndDate 
                THEN 'Reserved'
            WHEN r.Status = 'Primary' AND r.StartDate >= @StartDate AND r.EndDate <= @EndDate 
                THEN 'Sold'
            WHEN r.Status = 'Primary' AND r.StartDate >= DATEADD(YY,-1,GETDATE()) AND r.EndDate <= GETDATE() 
                THEN 'Refused'
            WHEN EXISTS (SELECT * FROM dbo.URL u WHERE u.URL = p.URL AND u.Date < DATEADD(YY,-2,GETDATE())) 
                THEN 'Needs Review'
            ELSE 
                'Available'
        END AS Availability
    FROM dbo.Product AS p 
    LEFT JOIN dbo.Reservation AS r
    ON p.Name = r.Title
)

我希望这是一个调用linq-to-sql的函数,然后我可以查询产品列表及其可用性。

编辑 - 以下是一些示例数据。

Products:
Name    URL                         Cost
-------------------------------------------
Gears   http://www.gearfinder.com   250
Shocks  http://www.shockfinder.com  110
Bolts   http://www.boltfinder.com   5



Reservations:
Title   Status        StartDate     EndDate
----------------------------------------------
Gears   Active        2012-01-01    2012-12-31
Gears   Primary       2012-01-01    2012-12-31
Gears   Inactive      2012-01-01    2012-12-31
Bolts   Inactive      2011-01-01    2011-12-31
Bolts   Active        2013-01-01    2013-12-31
Bolts   Primary       2014-01-01    2014-12-31

URLs:
URL                         Date
--------------------------------------
http://www.shockfinder.com  2010-01-01  

2 个答案:

答案 0 :(得分:0)

如果您不希望每个产品有超过9种状态,这可能会有效:

SELECT p.name, SUM(CASE WHEN r.Status = 'Active' AND r.StartDate >= @StartDate AND r.EndDate <= @EndDate THEN 10000 WHEN r.Status = 'Primary' AND r.StartDate >= @StartDate AND r.EndDate <= @EndDate THEN 1000 WHEN r.Status = 'Primary' AND r.StartDate >= DATEADD(YY,-1,GETDATE()) AND r.EndDate <= GETDATE() THEN 100 WHEN EXISTS (SELECT * FROM dbo.URL u WHERE u.URL = p.URL AND u.Date < DATEADD(YY,-2,GETDATE())) THEN 10 ELSE 0 END) AS Availability FROM dbo.Product AS p LEFT JOIN dbo.Reservation AS r ON p.Name = r.Title GROUP BY p.name

如果得分为0则可以使用。像10210这样的分数意味着您有1个保留,0个已售出,2个拒绝,以及1个需求已审核。如果您可以提供样本数据集,我们可能会更好地调整此查询。如果您查询的时间范围内任何p.name的任何一个状态超过9个,则无效。

另一种选择,将每个状态放入其自己的列中:

SELECT p.name, SUM(CASE WHEN r.Status = 'Active' AND r.StartDate >= @StartDate AND r.EndDate <= @EndDate THEN 1 ELSE 0 END) AS 'Reserved', SUM(CASE WHEN r.Status = 'Primary' AND r.StartDate >= @StartDate AND r.EndDate <= @EndDate THEN 1 ELSE 0 END) AS 'Sold', SUM(CASE WHEN r.Status = 'Primary' AND r.StartDate >= DATEADD(YY,-1,GETDATE()) AND r.EndDate <= GETDATE() THEN 1 ELSE 0 END) AS 'Refused', SUM(CASE WHEN EXISTS (SELECT * FROM dbo.URL u WHERE u.URL = p.URL AND u.Date < DATEADD(YY,-2,GETDATE())) THEN 1 ELSE 0 END) AS 'Needs Review', Count(*) AS 'Total Recs' FROM dbo.Product AS p LEFT JOIN dbo.Reservation AS r ON p.Name = r.Title GROUP BY p.name

这可以为您提供每种状态类型的计数,无论您拥有多少状态类型。

答案 1 :(得分:0)

这很好用。不确定它的最佳程度。

SELECT p.*,
    CASE
        WHEN 'Active' IN (SELECT r.Status FROM dbo.Reservation r WHERE r.Title = p.Name AND r.StartDate >= @StartDate AND r.EndDate <= @EndDate)
            THEN 'Reserved'
        WHEN 'Primary' IN (SELECT r.Status FROM dbo.Reservation r WHERE r.Title = p.Name AND r.StartDate >= @StartDate AND r.EndDate <= @EndDate)
            THEN 'Sold'
        WHEN 'Primary' IN (SELECT r.Status FROM dbo.Reservation r WHERE r.Title = p.Name AND r.StartDate >= DATEADD(YY,-1,GETDATE()) AND r.EndDate <= GETDATE() )
            THEN 'Refused'
        WHEN EXISTS (SELECT * FROM dbo.URL u WHERE u.URL = p.URL AND u.Date < DATEADD(YY,-2,GETDATE())) 
            THEN 'Needs Review'
        ELSE 
            'Available'
    END Availability
FROM dbo.Product AS p