我有一个名为tblCar
的表,有ID
,CarNumber
和其他32个字段。
32列填充为s1,s2,s3,.......,s32
,因为它们专门用于说明它是否适用于SEATS(A),预订(B)和售出(S)。
我想计算该数据库的可用座位,预订座位和售罄座位。 我该怎么写一个查询?
无论如何要从数据库中32个不同列的字符串S
,B
和A
进行计数?
我想表现的是...... 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();
这就是我为“Sold”字段工作的方式。但它只显示count = -128.i将计数初始化为0
答案 0 :(得分:3)
试试这个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");
}
}
}
答案 1 :(得分:0)
如果希望它返回值,则应使用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();
答案 2 :(得分:0)
由于您要返回1个值,因此应调用.ExecuteScalar
。 Upi还需要将返回值转换为int。
count = Convert.ToInt32(sqlcmd01.ExecuteScalar());
来自MSDN
执行查询,并返回查询返回的结果集中第一行的第一列。其他列或行将被忽略。
您只需要查找1个值,因此只需致电cmd.ExecuteScalar();
ExecuteNonQuery()
,ExecuteReader()
更适合其他事情。 (例如ExecuteNoNQuery()
的{{1}})
This SO Link很好地总结了这些差异。
答案 3 :(得分:0)
你有一个非常令人讨厌的表格结构,我会考虑改变它,但你得到了你可以做到这一点:
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)
答案 4 :(得分:-1)
我个人的建议是重新设计表格。仅使用3列,“可用”,“已售出”和“预订”。每列保持和int(bigint可能?),int将把具有该条件的所有席位的状态保存为二进制代码。例如,如果座位1,2,3和4是唯一的'已售出'座位,价值变为1 + 2 + 4 + 8 = 17.如果仅座位4& 5是“卖出”的价值将是8 + 16 = 24.这样你就不必查询所有列来查找卖出的座位,你只需要查询“已售出”列,它就会告诉你哪些座位是出售 。