【问题标题】:Data count from different columns in database来自数据库中不同列的数据计数
【发布时间】:2013-08-30 15:20:40
【问题描述】:

我有一个名为tblCar 的表,其中有IDCarNumber 和其他32 个字段。 32 列填写为s1,s2,s3,.......,s32,因为它们专用于备注它是否适用于 SEATS 可用(A)、预订(B)和 Sold(S)。

我想从该数据库计算可用座位、预订座位和售罄座位。 我应该如何编写查询?

是否可以从数据库中 32 个不同列的字符串 SBA 进行计数?

我想展示的是这样的.....S = 20, B = 10, A = 2;

SqlCommand cmd = new SqlCommand(
  "Select count(*) 
   FROM tblCar 
   WHERE s1= 'S' or s2= 'S' or s3= 'S' 
   or s4= 'S' or s5= 'S' or s6= 'S' 
   or s7= 'S' or s8= 'S' or s9= 'S' 
   or s10= 'S' or s11= 'S' or s12= 'S' 
   or s13= 'S' or s14= 'S' or s15= 'S' 
   or s16= 'S' or s17= 'S' or s18= 'S' 
   or s19= 'S' or s20= 'S' or s21= 'S' 
   or s22= 'S' or s23= 'S' or s24= 'S' 
   or s25= 'S' or s26= 'S' or s27= 'S' 
   or s28= 'S' or s29= 'S' or s30= 'S' 
   or s31= 'S' or s32= 'S' ", con
); 
count += cmd.ExecuteNonQuery(); 

这就是我为“已售”字段工作的方式。但它只显示 count = -128。我确实将计数初始化为 0

【问题讨论】:

  • 您有正在使用或尝试过的样品吗?
  • 试过s1+s2+s3.... AS s?
  • SqlCommand cmd = new SqlCommand("Select count(*) FROM tblCar WHERE s1= 'S' or s2= 'S' or s3= 'S' or s4= 'S' or s5= ' S' 或 s6= 'S' 或 s7= 'S' 或 s8= 'S' 或 s9= 'S' 或 s10= 'S' 或 s11= 'S' 或 s12= 'S' 或 s13= 'S'或 s14= 'S' 或 s15= 'S' 或 s16= 'S' 或 s17= 'S' 或 s18= 'S' 或 s19= 'S' 或 s20= 'S' 或 s21= 'S' 或 s22 = 'S' 或 s23= 'S' 或 s24= 'S' 或 s25= 'S' 或 s26= 'S' 或 s27= 'S' 或 s28= 'S' 或 s29= 'S' 或 s30= ' S' or s31= 'S' or s32= 'S' ", con);计数 += cmd.ExecuteNonQuery();这就是我为“已售”字段工作的方式。但它只显示计数 = -128。我确实将计数初始化为 0
  • @Kuroi Shinigami 您可以编辑您的问题以包含代码,以便它很好地理解 :)
  • 试试 cmd.ExecuteScalar()

标签: c# sql-server


【解决方案1】:

试试这个 sql 查询:

SELECT SUM(CASE WHEN State = 'S' THEN 1 ELSE 0 END) AS Sold
, SUM(CASE WHEN State = 'B' THEN 1 ELSE 0 END) AS Booked
, SUM(CASE WHEN State = 'A' THEN 1 ELSE 0 END) AS Available
FROM 
    (SELECT S1, S2, S3, S4, S5, S6
    FROM Seats) s
UNPIVOT
    (State FOR Seat IN (S1, S2, S3, S4, S5, S6)) AS rows;

这里SQL Fiddle

在示例中我只使用了 6 列,但在您的情况下,您需要为所有 32 列设置,但只需要一次

C#代码:

using SqlConnection conn = new SqlConnection(yourConnectionString)
{
    StringBuilder query = new StringBuilder();
    query.AppendLine("SELECT SUM(CASE WHEN State = 'S' THEN 1 ELSE 0 END) AS Sold");
    query.AppendLine(", SUM(CASE WHEN State = 'B' THEN 1 ELSE 0 END) AS Booked");
    query.AppendLine(", SUM(CASE WHEN State = 'A' THEN 1 ELSE 0 END) AS Available");
    query.AppendLine("FROM ");
    query.AppendLine("(SELECT S1, S2, S3, S4, S5, S6, S7, S8");
    query.AppendLine("(,S9, S10, S11, S12, S13, S14, S15, S16");
    query.AppendLine("(,S17, S18, S19, S20, S21, S22, S23, S24");
    query.AppendLine("(,S25, S26, S27, S28, S29, S30, S31, S32");
    query.AppendLine("FROM Seats) s");
    query.AppendLine("UNPIVOT");
    query.AppendLine("(State FOR Seat IN (S1, S2, S3, S4, S5, S6, S7, S8");
    query.AppendLine("(,S9, S10, S11, S12, S13, S14, S15, S16");
    query.AppendLine("(,S17, S18, S19, S20, S21, S22, S23, S24");
    query.AppendLine("(,S25, S26, S27, S28, S29, S30, S31, S32)) AS rows;");

    conn.Open();
    using SqlCommand command = new SqlCommand(query.ToString(), conn)
    {
        DataTable data = new DataTable();
        data.Load(command.ExecuteReader());
        //then get your values
        Int32 avialable = 0;
        Int32 booked= 0;
        Int32 sold = 0;
        if(data.Rows.Count > 0)
        {
            available = (Int32)data(0)("Available");
            booked = (Int32)data(0)("Booked");
            sold = (Int32)data(0)("Sold");
        }           
    }
}

【讨论】:

    【解决方案2】:

    你有一个非常糟糕的表结构,我会考虑改变它,但你可以这样做:

        SELECT SUM(CASE s1 WHEN 'S' THEN 1 ELSE 0 END) as sold,
         SUM(CASE s1 WHEN 'A' THEN 1 ELSE 0 END) as available,
         SUM(CASE s1 WHEN 'B' THEN 1 ELSE 0 END) as booked,
       FROM tblCar 
       UNION
        SELECT SUM(CASE s2 WHEN 'S' THEN 1 ELSE 0 END),
         SUM(CASE s2 WHEN 'A' THEN 1 ELSE 0 END),
         SUM(CASE s2 WHEN 'B' THEN 1 ELSE 0 END),
       UNION
        ... Repeat the above for each field.... yuck!...
       UNION
       SELECT SUM(CASE s32 WHEN 'S' THEN 1 ELSE 0 END),
         SUM(CASE s32 WHEN 'A' THEN 1 ELSE 0 END),
         SUM(CASE s32 WHEN 'B' THEN 1 ELSE 0 END)
    

    【讨论】:

    • 这个查询是不是太长了?
    • 我不能得到一个简单而简短的查询,它可以生成预订、已售和可用的计数吗? @凯尔
    【解决方案3】:

    由于您返回 1 个值,您应该调用 .ExecuteScalar。 Upi 还需要将 return 转换为 int。

    count = Convert.ToInt32(sqlcmd01.ExecuteScalar());
    

    来自 MSDN

    执行查询,并返回查询返回的结果集中第一行的第一列。其他列或行将被忽略。

    您只在寻找 1 个值,因此只需调用 cmd.ExecuteScalar(); ExecuteNonQuery()ExecuteReader() 就可以更好地处理其他事情。 (例如,ExecuteNoNQuery() 代表 INSERTS

    This SO Link 很好地总结了不同之处。

    【讨论】:

      【解决方案4】:

      如果你希望它返回一个值,你应该使用 ExecuteScalar。

      SqlCommand cmd = new SqlCommand("Select count(*) FROM tblCar WHERE s1= 'S' or s2= 'S' or s3= 'S' or s4= 'S' or s5= 'S' or s6= 'S' or s7= 'S' or s8= 'S' or s9= 'S' or s10= 'S' or s11= 'S' or s12= 'S' or s13= 'S' or s14= 'S' or s15= 'S' or s16= 'S' or s17= 'S' or s18= 'S' or s19= 'S' or s20= 'S' or s21= 'S' or s22= 'S' or s23= 'S' or s24= 'S' or s25= 'S' or s26= 'S' or s27= 'S' or s28= 'S' or s29= 'S' or s30= 'S' or s31= 'S' or s32= 'S' ", con); 
      count += (int)cmd.ExecuteScalar();
      

      【讨论】:

      • 出错了! count 是整数类型,返回的是一个对象。
      • count += (int)cmd.ExecuteScalar();
      • @Kuroi Shinigami 您需要转换为 Int。查看我的答案
      • 如果是这样,我只会得到已售出...我是否需要编写另一个查询以进行预订和可用?抱歉打扰了,因为我是一个新的初级程序员!
      【解决方案5】:

      我个人的建议是重新设计表格。仅使用 3 列,“available”、“sold”和“Booking”。每列都保存和 int(也许是 bigint?),该 int 将保存所有具有该条件的座位的状态作为二进制代码。例如,如果座位 1、2、3 和 4 是唯一“已售出”的座位,则价值变为 1+2+4+8 = 17。如果只有座位 4 和 5 被“售出”,则价值将为 8+16 = 24. 这样你就不需要查询所有的列来找到售出的座位,你只需要查询'sold'列,它就会告诉你哪些座位被售出 .

      【讨论】:

      • 如果以后座位数量增加到78个怎么办...?
      • 将每个类别分成两列或多列(因为 bigint 将不再包含二进制值)。到那时,您应该想要区分座位(“阳台”、“前排”甚至按排)。这仍然是比 78 列更好的解决方案。
      • 对我来说更好的解决方案是将数据库重新设计为Table('Cars'(ID, Number))Table('Seats'(ID,Name))Table('CarSeats'(CarID,SeatID,State),其中State 将保留有关座位可用性的信息。使用这种方法,如果汽车座椅的数量增加,您无需更改数据库。仅通过用户界面进行更改...
      • 以及如何在查询中从 24 中获取 2?这种设计不会阻止 3 在多个列中使用。
      • 按位运算符 '&' 将告诉您 24 中的 '2' 位是否打开。2 & 24 = true; 2 & 22 = 错误。而且您必须要么 A)在将其翻转到其他位置之前将其翻转为一个 B)使用触发器
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-03
      • 1970-01-01
      • 2012-03-15
      • 1970-01-01
      相关资源
      最近更新 更多