-1

我在计算带有内部连接的数据时遇到问题。

我想计算有多少小屋可用,这是我的表格:

在此处输入图像描述

在此处输入图像描述

这是我在课堂上获取小屋号码的代码。

public void CheckCottages()
 {
     con.Close();
     SqlCommand comUmbrella = new SqlCommand("CountCottages", con);
     comUmbrella.CommandType = CommandType.StoredProcedure;
     comUmbrella.Parameters.Add("@CottageType", SqlDbType.NVarChar).Value = "Umbrella";
     comUmbrella.Parameters.Add("@ReservedDate", SqlDbType.DateTime).Value = this.ARRIVAL;
     con.Open();
     comUmbrella.ExecuteNonQuery();
     drUmbrella = comUmbrella.ExecuteReader();
     if (drUmbrella.Read())
     {
         this.UMBRELLA = drUmbrella.GetInt32(drUmbrella.GetOrdinal("Rows"));
     }
     con.Close();
     SqlCommand comNativeKubo = new SqlCommand("CountCottages", con);
     comNativeKubo.CommandType = CommandType.StoredProcedure;
     comNativeKubo.Parameters.Add("@CottageType", SqlDbType.NVarChar).Value = "Native Kubo";
     comNativeKubo.Parameters.Add("@ReservedDate", SqlDbType.DateTime).Value = this.ARRIVAL;
     con.Open();
     comNativeKubo.ExecuteNonQuery();
     drKubo = comNativeKubo.ExecuteReader();
     if (drKubo.Read())
     {
         this.NATIVEKUBO = drKubo.GetInt32(drKubo.GetOrdinal("Rows"));
     }
     con.Close();
     SqlCommand comTreeHouse = new SqlCommand("CountCottages", con);
     comTreeHouse.CommandType = CommandType.StoredProcedure;
     comTreeHouse.Parameters.Add("@CottageType", SqlDbType.NVarChar).Value = "Tree house";
     comTreeHouse.Parameters.Add("@ReservedDate", SqlDbType.DateTime).Value = this.ARRIVAL;
     con.Open();
     comTreeHouse.ExecuteNonQuery();
     drTree = comTreeHouse.ExecuteReader();
     if (drTree.Read())
     {
         this.TREEHOUSE = drTree.GetInt32(drTree.GetOrdinal("Rows"));
     }
     con.Close();
     SqlCommand comPavillion = new SqlCommand("CountCottages", con);
     comPavillion.CommandType = CommandType.StoredProcedure;
     comPavillion.Parameters.Add("@CottageType", SqlDbType.NVarChar).Value = "Pavillion";
     comPavillion.Parameters.Add("@ReservedDate", SqlDbType.DateTime).Value = this.ARRIVAL;
     con.Open();
     comPavillion.ExecuteNonQuery();
     drPavillion = comPavillion.ExecuteReader();
     if (drPavillion.Read())
     {
         this.PAVILLION = drPavillion.GetInt32(drPavillion.GetOrdinal("Rows"));
     }
 }

这是我的存储过程:

ALTER PROCEDURE dbo.CountCottages
(
    @CottageType nvarchar(50),
    @ReservedDate datetime
)

AS
SELECT count(dbo.Cottages.CottageName)
FROM dbo.Cottages INNER JOIN
dbo.ResortTransactions ON dbo.Cottages.CottageID = dbo.ResortTransactions.CottageID
where dbo.Cottages.CottageType=@CottageType and dbo.ResortTransactions.Status != 'Cancelled' and dbo.ResortTransactions.ReservedDate != @ReservedDate

RETURN

我的代码有什么问题?我希望有一个人可以帮助我 :)

提前致谢!

4

4 回答 4

3

由于没有太多关于如何使用您的数据的信息,这里是一个猜测。我假设您想要一个有交易的小屋计数,其中 1) 状态未取消,2) 日期等于预订日期。如果是这样,这是查询:

SELECT count(dbo.Cottages.CottageName)
    FROM dbo.Cottages 
    WERE CottageType=@CottageType 
        AND CottageID NOT IN
        (SELECT CottageID FROM dbo.ResortTransactions
         WHERE Status != 'Cancelled' 
         AND ReservedDate = @ReservedDate)

此外,您正在执行存储过程两次 - 一次使用ExecuteNonQuery和一次使用ExecuteReader您应该返回一个值并使用ExecuteNonQuery,创建一个参数来存储返回值,或者使用ExecuteScalar快速从数据集中提取第一个结果。

我建议阅读更多关于基本 SQL 以及如何使用 .NET 执行查询的内容。

于 2012-09-25T13:23:51.827 回答
1

您不返回COUNT.

声明一个变量,用结果初始化它并从过程中返回它:

ALTER PROCEDURE dbo.CountCottages
(
    @CottageType nvarchar(50),
    @ReservedDate datetime
)
AS
BEGIN

DECLARE @NumCottages int
SELECT @NumCottages = count(dbo.Cottages.CottageName)
FROM dbo.Cottages INNER JOIN
dbo.ResortTransactions ON dbo.Cottages.CottageID = dbo.ResortTransactions.CottageID
where dbo.Cottages.CottageType=@CottageType and dbo.ResortTransactions.Status != 'Cancelled' and dbo.ResortTransactions.ReservedDate != @ReservedDate

RETURN @NumCottages

END

然后使用SqlCommand.ExecuteScalar代替ExecuteNonQuery来获取值。

于 2012-09-25T13:23:36.573 回答
1

Cmd.ExeceuteNonQuery()通常用于执行过程而不期望返回结果。但是在这里你正在寻找一个标量值。所以将它更改为cmd.ExecuteScalar()。同时从过程中返回计数。

于 2012-09-25T13:23:44.177 回答
0

我会做一些假设——只是一个小技巧,在玩这个的时候我会在 SQL 查询中创建一个“便签本”并使用表变量进行测试,如下所示:

DECLARE @Cottages AS TABLE
    (
      Cottage_PK INT IDENTITY(1, 1) ,
      CottageName VARCHAR(100) ,
      CottageType VARCHAR(100)
    )
DECLARE @Reservations AS TABLE
    (
      Reservation_PK INT IDENTITY(1, 1) ,
      Cottage_FK INT ,
      CheckinDate DATETIME ,
      DepatureDate DATETIME ,
      IsCanceled BIT
    )
DECLARE @DateToCheck AS DATETIME ,
    @CottageType AS VARCHAR(100)
SET @DateToCheck = '2012-09-15'
SET @CottageType = 'Some Type'
INSERT  INTO @Cottages
        ( CottageName, CottageType )
VALUES  ( 'CottageA', 'Some Type' )
INSERT  INTO @Reservations
        ( Cottage_FK ,
          CheckinDate ,
          DepatureDate ,
          [Status]
        )
VALUES  ( 1 , -- Cottage_FK - int
          '2012-09-16' , -- CheckinDate - datetime
          '2012-09-24' ,  -- DepatureDate - datetime
          ''
        )

现在我假设如果您想检查某个日期可用的小屋,您需要根据入住日期和出发日期进行检查,这会导致使用between声明。

SELECT  COUNT(c.CottageName) AS 'Cottages availible'
FROM    @Cottages c
        INNER JOIN @Reservations r ON c.Cottage_PK = r.Cottage_FK
WHERE   NOT @DateToCheck BETWEEN r.CheckinDate
                         AND     r.DepatureDate
        AND c.[status] != 'Cancelled'
        AND c.CottageType = @CottageType

使用它进行测试 - 我在它返回 0 的范围内传递了一个日期,并且它返回了 1。一旦你很高兴将它移动到你的存储过程。

CREATE PROCEDURE dbo.CountCottages
    @DateToCheck DATETIME ,
    @CottageType VARCHAR(100)
AS 
    SELECT  COUNT(c.CottageName) AS 'Cottages availible'
    FROM    Cottages c
            INNER JOIN ResortTransactions r ON c.Cottage_PK = r.Cottage_FK
    WHERE   NOT @DateToCheck BETWEEN r.CheckinDate
                             AND     r.DepatureDate
            AND c.[status] != 'Cancelled'
            AND c.CottageType = @CottageType
于 2012-09-25T13:36:48.593 回答