So first here is my C# code and then comes the stored procedure.
public DataTable GetCourseHighPass(String tmpCourse)
{
command.Connection = OpenConnection();
try
{
command.CommandText = "exec GetCourseCompletions #tmpCourse = '" + tmpCourse + "'";
SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
dataAdapter.Fill(dataTable);
return dataTable;
}
catch (Exception)
{
throw new Exception("There are no VG's for this course.");
}
finally
{
command.Connection.Close();
}
}
And here is my stored procedure.
create procedure GetCourseCompletions
#tmpCourse nvarchar(30)
as
select (count(pnr) * 100 / (select count(pnr)
from HasStudied
where courseCode = #tmpCourse
and count(pnr) =)) as VGPrecentage
from HasStudied
where grade >= 5
and courseCode = #tmpCourse
go
The problem is that if there are no students with a high pass I will get a divide by zero exception. Looking for suggestions on how to catch this exception so the program does not crash or even better to re-write the stored procedure so it does not get an exception in the first place.
Thank you for your assistance!
Do what Eric said:
DECLARE #count int
Set #count = (select count(pnr) from HasStudied where courseCode = #tmpCourse and count(pnr) =...)
IF #count = 0
BEGIN
SELECT 0 as VGPrecentage
END
ELSE
BEGIN
select (count(pnr)*100 / #count) as VGPrecentage from HasStudied where grade >= 5 and courseCode = #tmpCourse
END
I suggest you to use this kind of query instead of yours that will handle NULL values and Zero values:
SELECT
CASE WHEN part * total <> 0 THEN part * 100 / total ELSE 0 END
FROM (
SELECT SUM(CASE WHEN grade > 5 THEN 1.00 ELSE 0.00 END) As part, SUM(1.00) as total
FROM HasStudied
WHERE courseCode = #tmpCourse) t
Related
I am trying to fill a DataTable reading a view using SqliteDataReader. The following code works when I am reading a Table (not a view)
private DataTable ReadDataTable(SqliteCommand command)
{
DataTable result = new();
using (var connection = Connection)
{
connection.Open();
SqliteDataReader reader = command.ExecuteReader();
result.Load(reader);
}
return result;
}
However, when the table in question is a view, containing multiple rows, the resulting table only contains one row. To test I tried the following function, running the same command
private int ReadDataTableTest(SqliteCommand command)
{
int result = 0;
using (var connection = Connection)
{
connection.Open();
SqliteDataReader reader = command.ExecuteReader();
while(reader.Read())
result++;
}
return result;
}
This returned 6, the correct answer. Also, querying the table directly in SqliteStudio gives the right answer. The top function seems only to insert the last row of the reader in the DataTable. What is going on here?
Btw, I don't know for sure that the issue is that the table is a view, but I have a similar issue with many other views, and the "view/table" thing seems to be the common denominator.
I am using Windows, coding in .net6. using the following imports
using Microsoft.Data.Sqlite;
using System.Data;
EDIT
I am creating the command like this
private SqliteCommand CreateCommand(string tableName, DateTime reportDate)
{
var command = Connection.CreateCommand();
command.CommandText = #$"SELECT * FROM {tableName} WHERE ReportDate = $reportDate";
command.Parameters.AddWithValue("$reportDate", reportDate.ToSqliteDate());
return command;
}
And calling the code like this
var reportDate = new DateTime(2022, 7, 31);
var table = ReadDataTable(CreateCommand("MyTable", reportDate));
I am not doing anything to the table after the call.
EDIT 2
The following query generates the view
SELECT [of].ReportDate,
[of].Entity,
SUM(CASE WHEN [of].Item IN ('Equity') THEN [of].Value / fx.FxRate ELSE 0 END) AS EquityLocal,
SUM(CASE WHEN [of].Item IN ('AdjIFRS') THEN [of].Value / fx.FxRate ELSE 0 END) AS AdjIFRSLocal,
SUM(CASE WHEN [of].Item IN ('AdjIFRSGroup') THEN [of].Value / fx.FxRate ELSE 0 END) AS AdjIFRSGroup,
SUM(CASE WHEN Entity != 'Holding' AND
[of].Item IN ('Equity', 'AdjIFRS', 'AdjIFRSGroup') THEN -[of].Value / fx.FxRate ELSE 0 END) AS Elimination,
SUM(CASE WHEN Entity = 'Holding' AND
[of].Item IN ('Equity', 'AdjIFRS', 'AdjIFRSGroup') THEN [of].Value / fx.FxRate ELSE 0 END) AS EquityIFRS,
'EUR' AS ReportCurrency
FROM InputOwnFunds AS [of]
JOIN InputEurFxRates AS fx
ON [of].ReportDate = fx.ReportDate AND
[of].ReportCurrency = fx.ReportCurrency
WHERE of.Item in ('Equity', 'AdjIFRS', 'AdjIFRSGroup')
GROUP BY [of].ReportDate,
[of].Entity
UNION
SELECT [of].ReportDate,
'NLP Group' as Entity,
SUM(CASE WHEN [of].Item IN ('Equity') THEN [of].Value / fx.FxRate ELSE 0 END) AS EquityLocal,
SUM(CASE WHEN [of].Item IN ('AdjIFRS') THEN [of].Value / fx.FxRate ELSE 0 END) AS AdjIFRSLocal,
SUM(CASE WHEN [of].Item IN ('AdjIFRSGroup') THEN [of].Value / fx.FxRate ELSE 0 END) AS AdjIFRSGroup,
SUM(CASE WHEN Entity != 'Holding' AND
[of].Item IN ('Equity', 'AdjIFRS', 'AdjIFRSGroup') THEN -[of].Value / fx.FxRate ELSE 0 END) AS Elimination,
SUM(CASE WHEN Entity = 'Holding' AND
[of].Item IN ('Equity', 'AdjIFRS', 'AdjIFRSGroup') THEN [of].Value / fx.FxRate ELSE 0 END) AS EquityIFRS,
'EUR' AS ReportCurrency
FROM InputOwnFunds AS [of]
JOIN InputEurFxRates AS fx
ON [of].ReportDate = fx.ReportDate AND
[of].ReportCurrency = fx.ReportCurrency
WHERE of.Item in ('Equity', 'AdjIFRS', 'AdjIFRSGroup')
GROUP BY [of].ReportDate
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 7 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
I am fetching quarterly records from sql server. The records are like total debits and credits in each quarter of year. In my sql query I have made the quarters and the year is dynamic as you can see in the code.
public List<QuarterlyExpenseList> GetExpenseDataQuarterly(string Id, string Year)
{
string SQL = "select aspnetusers.username, SUM(case when Expense.Type='credit' and (Expense.Date>='#year-01-01' and Expense.Date<='#year-03-31') then Expense.Amount else 0 end) as QuarterOneCredits,";
SQL += " SUM(case when Expense.Type='credit' and (Expense.Date>='#year-04-01' and Expense.Date<='#year-06-30') then Expense.Amount else 0 end) as QuarterTwoCredits,";
SQL += " SUM(case when Expense.Type='credit' and (Expense.Date>='#year-07-01' and Expense.Date<='#year-09-30') then Expense.Amount else 0 end) as QuarterThreeCredits,";
SQL += " SUM(case when Expense.Type='credit' and (Expense.Date>='#year-10-01' and Expense.Date<='#year-12-31') then Expense.Amount else 0 end) as QuarterFourCredits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>='#year-01-01' and Expense.Date<='#year-03-31') then Expense.Amount else 0 end) as QuarterOneDebits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>='#year-04-01' and Expense.Date<='#year-06-30') then Expense.Amount else 0 end) as QuarterTwoDebits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>='#year-07-01' and Expense.Date<='#year-09-30') then Expense.Amount else 0 end) as QuarterThreeDebits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>='#year-10-01' and Expense.Date<='#year-12-31') then Expense.Amount else 0 end) as QuarterFourDebits";
SQL += " from Expense inner join AspNetUsers on AspNetUsers.Id=Expense.MadeBy";
if (Id == null)
{
SQL += " group by aspnetusers.username";
}
else
{
SQL += " where Expense.MadeBy=#id group by AspNetUsers.UserName group by aspnetusers.username";
}
using (IDbConnection cn=Connection)
{
cn.Open();
List<QuarterlyExpenseList> objList = cn.Query<QuarterlyExpenseList>(SQL, new { year = Year, id = Id }).ToList();
return objList;
}
}
here I am getting an exception of Conversion failed when converting date and/or time from character string. Can somebody tell me what does it mean and how can I get rid of it
I removed the dynamic year "#year" outside character string as it is a dynamic value. When written like '#year-04-01' SQL was treating "#year" as a character string and not as a dynamic value.
Use the following code:
public List<QuarterlyExpenseList> GetExpenseDataQuarterly(string Id, string Year)
{
string SQL = "select aspnetusers.username, SUM(case when Expense.Type='credit' and (Expense.Date>=#year+'-01-01' and Expense.Date<=#year+'-03-31') then Expense.Amount else 0 end) as QuarterOneCredits,";
SQL += " SUM(case when Expense.Type='credit' and (Expense.Date>=#year+'-04-01' and Expense.Date<=#year+'-06-30') then Expense.Amount else 0 end) as QuarterTwoCredits,";
SQL += " SUM(case when Expense.Type='credit' and (Expense.Date>=#year+'-07-01' and Expense.Date<=#year+'-09-30') then Expense.Amount else 0 end) as QuarterThreeCredits,";
SQL += " SUM(case when Expense.Type='credit' and (Expense.Date>=#year+'-10-01' and Expense.Date<=#year+'-12-31') then Expense.Amount else 0 end) as QuarterFourCredits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>=#year+'-01-01' and Expense.Date<=#year+'-03-31') then Expense.Amount else 0 end) as QuarterOneDebits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>=#year+'-04-01' and Expense.Date<=#year+'-06-30') then Expense.Amount else 0 end) as QuarterTwoDebits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>=#year+'-07-01' and Expense.Date<=#year+'-09-30') then Expense.Amount else 0 end) as QuarterThreeDebits,";
SQL += " SUM(case when Expense.Type='debit' and (Expense.Date>=#year+'-10-01' and Expense.Date<=#year+'-12-31') then Expense.Amount else 0 end) as QuarterFourDebits";
SQL += " from Expense inner join AspNetUsers on AspNetUsers.Id=Expense.MadeBy";
if (Id == null)
{
SQL += " group by aspnetusers.username";
}
else
{
SQL += " where Expense.MadeBy=#id group by AspNetUsers.UserName group by aspnetusers.username";
}
using (IDbConnection cn=Connection)
{
cn.Open();
List<QuarterlyExpenseList> objList = cn.Query<QuarterlyExpenseList>(SQL, new { year = Year, id = Id }).ToList();
return objList;
}
}
My sql table contains date of birth of many people.dates are in mm/dd/yyyy format. I want select the persons details whose birth day in next 30days. And i use the following query for that,
SELECT Mem_FirstNA, Mem_LastNA, Mem_DOB FROM MemberDetails WHERE
ltrim(str(year(GETDATE()))) + -' + ltrim(str(month(Mem_DOB))) + '-' +
ltrim(str(day(Mem_DOB))) >= getdate() - 1 AND
ltrim(str(year(GETDATE()))) + '-' + ltrim(str(month(Mem_DOB))) + '-' +
ltrim(str(day(Mem_DOB))) <= getdate() + 30
And full code is
public List<MemberData> GetThisMonthBirthday()
{
List<MemberData> MD = new List<MemberData>();
using (SqlConnection con = new SqlConnection(Config.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("SELECT Mem_FirstNA, Mem_LastNA, Mem_DOB FROM MemberDetails WHERE ltrim(str(year(GETDATE()))) + '-' + ltrim(str(month(Mem_DOB))) + '-' + ltrim(str(day(Mem_DOB))) >= getdate() - 1 AND ltrim(str(year(GETDATE()))) + '-' + ltrim(str(month(Mem_DOB))) + '-' + ltrim(str(day(Mem_DOB))) <= getdate() + 30", con))
{
try
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
MemberData mb = new MemberData();
mb.Mem_NA = (string)reader["Mem_FirstNA"];
mb.Mem_LastNA =(string)reader["Mem_LastNA"];
mb.Mem_DOB = (Convert.ToDateTime(reader["Mem_DOB"]));
MD.Add(mb);
}
}
catch (Exception e) { throw e; }
finally { if (con.State == System.Data.ConnectionState.Open) con.Close(); }
return MD;
}
}
The problem is that this check only till December 31, if the persons birthday in 01/01/1987 , the query is not selected that details. Please help me to solve this problem. Thank you
There are lots of ways to do this, you need conditional logic depending on whether or not you are within 30 days of the end of the year. If you're using SQL Server, I'd wrap the logic in a function to make it more readable, e.g.:
CREATE FUNCTION [dbo].[IsBirthdayInRange]
(
#Birthday DATETIME,
#StartDate DATETIME,
#EndDate DATETIME
)
RETURNS BIT
AS
BEGIN
DECLARE #StartMonthDay INT
DECLARE #EndMonthDay INT
DECLARE #BirthdayMonthDay INT
SET #StartMonthDay = MONTH(#StartDate) * 100 + DAY(#StartDate)
SET #EndMonthDay = MONTH(#EndDate) * 100 + DAY(#EndDate)
SET #BirthdayMonthDay = MONTH(#Birthday) * 100 + DAY(#Birthday)
IF YEAR(#StartDate) <> YEAR(#EndDate)
BEGIN
IF #BirthdayMonthDay >= #StartMonthDay OR #BirthdayMonthDay <= #EndMonthDay
BEGIN
RETURN 1
END
END
ELSE
BEGIN
IF #BirthdayMonthDay >= #StartMonthDay AND #BirthdayMonthDay <= #EndMonthDay
BEGIN
RETURN 1
END
END
RETURN 0
END
You can then use it as:
...
WHERE IsBirthdayInRange(Mem_DOB, GETDATE(), GETDATE() + 30)
I have a stored procedure with the following code, it works fine in sql server. I need to use the returned rows to work with the stacked column chart. I don't know how to receive these rows, though I have tried to do so with code given after the stored procedure code. I would really appreciate if anyone could find out where I am doing something wrong. Thank you :)
Stored Procedure Code:
ALTER PROCEDURE [dbo].[weekly]
#id_beleg int /* CONTAINS THE ID OF THE MACHINE FOR WHICH THE NUMBER OF ORDERS IS REQUIRED*/
AS
BEGIN
DECLARE #montag DATETIME
DECLARE #weekend DATETIME
SET #montag = DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)
/* SET #MONTAG VARIABLE TO THE DATE ON MONDAY OF THE CURRENT WEEK*/
SET #weekend = dateadd(day, 6, #montag)
/* SET #WEEKEND VARIABLE TO THE DATE ON SUNDAY OF THE CURRENT WEEK*/
/* CONTAINS ALL RECORDS OF one PROCESS FOR THE CURRENT WEEK*/
CREATE TABLE #WeeklySieben
(
Tag datetime,
Aufträge_anzahl int,
Anlage varchar(30)
);
INSERT INTO #WeeklySieben (Tag, Aufträge_anzahl, Anlage)
SELECT *
FROM
dbo.Sieben
WHERE
Tag BETWEEN #montag AND GETDATE()
ORDER BY Tag
DECLARE #tempdate datetime
/* CONTAINS ONLY THE UNIQUE MACHINE NAMES*/
CREATE TABLE #Anlage_Sieben
(
Anl varchar(30)
)
/* CONTAINS DATE FOR ALL DAYS OF THE CURRENT WEEK*/
CREATE TABLE #alldays
(
days datetime
)
INSERT INTO #Anlage_Sieben (Anl)
SELECT KURZTEXT as Anl
FROM dbo.tblBELEGUNGSEINHEIT
WHERE ID in (SELECT ID_BELEGUNGSEINHEIT FROM dbo.tblPROZESS_BELEGUNGSEINHEIT WHERE ID_PROZESS = 5)
/* SELECT MACHINE ID WHERE PROCESS IS number 5*/
WHILE #montag <= #weekend
BEGIN
INSERT INTO #alldays (days)
SELECT days = #montag
SET #tempdate= #montag
SET #montag = dateadd(day, 1,#tempdate)
END
/* MACHINE NAME * WEEKDAYS DATE*/
CREATE TABLE #weekdays
(
daydate datetime,
Anlage varchar(30)
)
INSERT INTO #weekdays (daydate, Anlage)
SELECT d.days as daydate
, a.Anl as Anlage
FROM #Anlage_Sieben a
CROSS JOIN #alldays d
/* SELECT NUMBER OF ORDERS ON A PARTICULAR MACHINE FOR ALL WEEK DAYS*/
Select case
when Aufträge_anzahl is null then '0'
else Aufträge_anzahl
end
from #WeeklySieben W right join #weekdays wd on W.Anlage = wd.Anlage and W.Tag = wd.daydate
where wd.Anlage in (select KURZTEXT from dbo.tblBELEGUNGSEINHEIT where ID = #id_beleg )
END
C# Code:
try
{
int a;
string sql = "weekly";
SqlDataAdapter dp = new SqlDataAdapter();
SqlCommand c = null;
SqlDataReader r = null;
DataSet ds = new DataSet();
DataTable dt = new DataTable();
//For creating 'raum' number of stacked column bars
for (int i = 0; i < raum; i++)
{
c = new SqlCommand(sql, conn);
c.CommandType = CommandType.StoredProcedure;
c.Parameters.Add("#raumn", SqlDbType.Int).Value= (int)dblOrders[i];
r = c.ExecuteReader();
dp.SelectCommand = c;
dp.Fill(ds, "Aufträge_anzahl");
dt = ds.Tables["Aufträge_anzahl"];
//For adding points to a stacked column bar
for (int j = 0; j < dt.Rows.Count; j++)
{
a = Convert.ToInt32(dt.Rows[j]);
Chart1.Series[seriesArray[j]].Points.AddY(a);
}
Chart1.DataBind();
dtSr.Clear();
}
}
catch (SqlException ex)
{
Console.WriteLine("SQL Error" + ex.Message.ToString());
}
dblorders is the double array which holds the IDs for different machines, raum is the number of total machines. The code generates no error, but it does not retrieve back the data in the chart.
I have a table which contains a two column(start_time and end_time).I am getting the information of start and end time from the user and adding it to the table.Once the user enters the next start and end time I have to compare it with the database.
Suppose in table one row has start time as 2011-08-10 16:00:00 and end time is 2011-08-10 16:30:00.
Suppose the user enter value 2011-08-10 16:05:00.000 (start_time) and 2011-08-10 16:25:00 (end_time) I am able to capture the by using
String getConflictTimeInBetween = string.Format("select question_id,question_text from " + data_variables.RES_TXT_STRING_QUESTION_TABLE + " where start_time<='{0}' and end_time>='{1}'", start_full, end_full);//question_text='DFS'"2011-06-23 14:55);//
com = new SqlCommand(getConflictTimeInBetween, myConnection);
dr = com.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
//Assign to your textbox here
conflictQuestionIdAtBetween = dr["question_id"].ToString();
conflictQuestionTextAtBetween=dr["question_text"].ToString();
}
}
Here are some sample overlaps that I want to prevent
start_time from 2011-08-10 15:55:00 and end_time 2011-08-10 16:05:00 (five minutes overlap with already existing data)
start_time from 2011-08-10 16:25:00 and end_time 2011-08-10 17:00:00 (five minutes overlap with already existing data)
start_time from 2011-08-10 15:00:00 and end_time 2011-08-10 17:00:00 (30 minutes overlap with already existing data)
Can anyone help me how to solve these three issues.
None of the 3 overlapping scenarios you mentioned will show up with the query you're using now. It's not clear from your post what you mean to achieve, but I can give you the queries that will show each scenario:
1) "select question_id,question_text from " + data_variables.RES_TXT_STRING_QUESTION_TABLE + " where start_time>'{0}' and start_time<'{1}'", start_full, end_full);//question_text='DFS'"2011-06-23 14:55);
2) "select question_id,question_text from " + data_variables.RES_TXT_STRING_QUESTION_TABLE + " where end_time>'{0}' and end_time<'{1}'", start_full, end_full);//question_text='DFS'"2011-06-23 14:55);
3) "select question_id,question_text from " + data_variables.RES_TXT_STRING_QUESTION_TABLE + " where start_time>'{0}' and end_time<'{1}'", start_full, end_full);//question_text='DFS'"2011-06-23 14:55);
Since you seem to have the SQL part, here's the algorithm that finds the overlap in ticks between the input time and the row time.
public long GetTimeOverlap(long inputStart, long inputEnd)
{
// I assume you can get the data yourself so heres only the algorithm.
long rowStart = new DateTime().Ticks, rowEnd = new DateTime().Ticks;
if (inputStart < rowStart)
if (inputEnd >= rowEnd)
// case 3
return rowEnd - rowStart;
else if (inputEnd > rowStart)
// case 1
return inputEnd - rowStart;
// Input time is before row time.
else return 0;
else if (inputStart >= rowEnd)
// Input time is after row time.
return 0;
else if (inputEnd >= rowEnd)
// case 2
return rowEnd - inputStart;
// case 0
else return inputEnd - inputStart;
}
Not sure what you mean in your question, however here is much better code:
String getConflictTimeInBetween = string.Format("select question_id,question_text from {0} where start_time<=#start and end_time>=#end", data_variables.RES_TXT_STRING_QUESTION_TABLE);
using (com = new SqlCommand(getConflictTimeInBetween, myConnection))
{
com.Parameters.AddWithValue("#start", Convert.ToDateTime(start_full));
com.Parameters.AddWithValue("#end", Convert.ToDateTime(end_full));
using (dr = com.ExecuteReader())
{
if (dr.HasRows)
{
while (dr.Read())
{
//Assign to your textbox here
conflictQuestionIdAtBetween = dr["question_id"].ToString();
conflictQuestionTextAtBetween=dr["question_text"].ToString();
}
}
}
}
It's doing the same thing plus:
Prevent possible SQL Injection attacks by using Parameters instead of directly injecting the text.
Dispose the objects (command and reader) after using them to prevent connections from remaining open and crashing your database. This is done by the using blocks.
I believe what you want to do to intersect the date ranges correctly is something like:
String getConflictTimeInBetween = string.Format("select question_id,question_text from " + data_variables.RES_TXT_STRING_QUESTION_TABLE + "where (start_time<='{0}' and end_time>='{0}') or ((start_time<='{1}' and end_time>='{1}')", start_full, end_full);