所以这是我的问题,请参阅随附的屏幕截图,这样您就会看到我显示的是 11 月 1 到 30 个日期。
现在在左侧我显示公司名称。
现在我有两个表,一个是 CompanyData,另一个是 CompanyDataBooking。
在 CompanyData 表中,我们存储公司的基本数据,如名称、Guid 等。
在 CompanyDataBooking 表中,我们存储在任何日期预订的特定公司的数据。
公司数据表:
公司ID | 姓名 |
---|---|
4C3ABCC2-8AA5-EF11-BC69-70321710CB7E | 公司1 |
4C3ABCC2-8AA5-EF11-BC69-70321710CB7F | 公司2 |
公司数据预订表:
记录ID | 公司ID | 日期 |
---|---|---|
C1CB71EC-8AA5-EF11-BC69-70321710CB7D | 4C3ABCC2-8AA5-EF11-BC69-70321710CB7E | 2024-11-15 00:00:00.000 |
C1CB71EC-8AA5-EF11-BC69-70321710CB7E | 4C3ABCC2-8AA5-EF11-BC69-70321710CB7F | 2024-11-25 00:00:00.000 |
例如,在上面的屏幕截图中,您可以在 CompanyData 中看到我们有基本数据,在 CompanyDataBooking 表中您可以看到 CompanyId 作为外键,并且还有一个日期字段,我们在其中存储像预订日期的 CompanyId 一样。
所以我想要的是,在该网格中,如果 CompanyDataBooking 表中有特定的公司日期,那么它将显示为“已预订”,或者它将显示为“可用”。
我所做的是创建了一个查询,该查询将运行并返回 11 月 1 日至 30 日的数据,但我不确定是否应该进一步显示特定公司特定日期的数据(无论是否预订)。
我已经进行了以下查询来获取数据,但不确定它是否好或者我需要采用其他方法..
select cr.CompanyId
from CompanyDataBooking cdb
left join CompanyData cr on cr.CompanyId = crb.CompanyId
where month = 11
谢谢
好吧,这里的挑战很大程度上在于您必须将行“转换”为列。虽然 SQL Server 确实有转换,但它不会为一个月中的所有天生成列。
因此,我建议进行查询,然后将行处理到您在代码中创建的新表中。
并且,一旦我们完成了上述操作,那么将数据表发送到 UI 就变得很简单了。
我没有 MVC 示例,但这个 Webforms 示例将为您提供如何解决此问题的概念证明。
所以,说一下我们的标记(我使用了 GridView,但在 MVC 中,您可以简单地循环标题和行来输出 HTML 表格 - 这就是 GridView 所做的全部)。
标记:
<h4 id="HotelHead" runat="server">Hotel Booking Summary</h4>
<asp:GridView ID="GVBookings" runat="server"
CssClass="table table-hover"
OnRowDataBound="GVBookings_RowDataBound">
</asp:GridView>
现在是后面的代码。我决定在日历中记录当天的预订“计数”。但是,您可以轻松地简单地显示一些符号、字母或其他内容。
我还为一个月中的任何一天添加了显示一些预订的背景颜色。
因此,在这个示例中,我们的设置与您的问题大致相同。
我有一张酒店表,还有一张预订表。就像您的问题一样,简单的左连接即可获取我们的数据。但是请记住,您需要将“月”和“年”条件应用于子联接表,而不是在联接之后,因为这样会使左联接不起作用(因为没有任何预订的酒店将不会被包括在内)在列表中)。因此,请注意我们在子(左连接)表中使用 where 子句的位置和方式。
因此,代码提取表(我们的联接)。 然后,我们将数据处理到内存中的一个新表中,其中包含酒店名称,然后是该月的日期。
背后代码:
int Month = 9;
int Year = 2024;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
string MonthName = new DateTimeFormatInfo().GetMonthName(Month);
HotelHead.InnerText = $"Hotel Bookings for {MonthName} - {Year}";
string strSQL =
$@"select HotelName, Bookings.BookingDate from tblHotelsA
LEFT Join Bookings on
bookings.Hotel_ID = tblHotelsA.id
AND (MONTH(Bookings.BookingDate) = {Month}
AND Year(Bookings.BookingDate) = {Year})
WHERE tblHotelsA.Active = 1
ORDER BY HotelName";
DataTable dtHotels = General.MyRst(strSQL);
DataTable dtOneMonth = new DataTable();
dtOneMonth.Columns.Add("HotelName");
DateTime dtStart = new DateTime(Year, Month, 1);
int DaysInMonth = DateTime.DaysInMonth(Year, Month);
// add number of columns for days in the month
for (int i = 1; i <= DaysInMonth; i++)
dtOneMonth.Columns.Add(i.ToString(),typeof(int));
// process row data into cross tab (across data)
string CurrentHotel = "";
DataRow OutPut = null;
foreach (DataRow dr in dtHotels.Rows)
{
if (CurrentHotel != dr["HotelName"].ToString())
{
if (OutPut != null) // hotel name changed, start a new output row
dtOneMonth.Rows.Add(OutPut);
OutPut = dtOneMonth.NewRow();
CurrentHotel = dr["HotelName"].ToString();
OutPut["HotelName"] = CurrentHotel;
}
if (!DBNull.Value.Equals(dr["BookingDate"]))
{
int DayIndex = ((DateTime)dr["BookingDate"]).Day;
if (DBNull.Value.Equals(OutPut[DayIndex]))
OutPut[DayIndex] = 0;
OutPut[DayIndex] = (int)OutPut[DayIndex] + 1;
}
}
dtOneMonth.Rows.Add(OutPut);
GVBookings.DataSource = dtOneMonth;
GVBookings.DataBind();
}
protected void GVBookings_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
for (int i = 1; i <= e.Row.Cells.Count - 1; i++)
{
DateTime cDate = new DateTime(Year, Month, i);
e.Row.Cells[i].Text += $"<br/>{cDate.ToString("ddd")}";
e.Row.Cells[i].Style.Add("text-align", "center");
}
}
if (e.Row.RowType == DataControlRowType.DataRow)
{
for (int i = 1; i <= e.Row.Cells.Count - 1; i++)
{
if (e.Row.Cells[i].Text != " ")
{
e.Row.Cells[i].BackColor = System.Drawing.Color.LightSkyBlue;
e.Row.Cells[i].Style.Add("text-align", "center");
}
}
}
}
结果是这样的:
事实上,上面的很多代码行都可以删除,但我想要一些突出显示。我确实应用了引导表类,因此生成的表输出是响应式布局。