Visual Studio (2017) SQL cannot display % sign - sql-server

I am aware that there are differences between Oracle SQL and SQL Server. The query runs fine and displays the result well but the issue arises when I want to display it on a pie chart. I am thinking that it might be some Visual Studio restriction.
Here is my SQL statement:
SELECT
CAST(ROUND(CAST(COUNT(LoanAcNo) AS FLOAT) / 73 * 100, 1) AS VARCHAR) + '%' AS LoanPercentage,
LoanType
FROM
Loan
GROUP BY
LoanType;
This is how I implemented it:
public DataSet ReadLoanByLoanType()
{
SqlConnection myConn = new SqlConnection(DBConnect);
StringBuilder sqlStr = new StringBuilder();
sqlStr.AppendLine("SELECT cast( round( cast ( count(LoanAcNo) as float) / 73 * 100 , 1 ) as varchar ) + '%' as LoanPercentage , LoanType");
sqlStr.AppendLine("FROM Loan");
sqlStr.AppendLine("GROUP BY LoanType");
SqlDataAdapter da = new SqlDataAdapter(sqlStr.ToString(), myConn);
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}

If you want to download values from a database for inclusion in some reporting tool's pie chart, don't turn the value into a string by adding a '%' onto them
Your reports tool will be expecting some numeric value to chart, not a string
SQL:
SELECT
round(count(LoanAcNo)/ 73.0 * 100.0, 1) as LoanPercentage,
LoanType
FROM Loan
GROUP BY LoanType;
Tip: dividing an integer by a constant number that has a decimal place (e.g. I divided by 73.0 instead of 73) rather than an integer should make SQLS do the calc using floats - saves you having to cast the int to float/makes the SQL shorter and neater

Related

How can I use a SQL Server column of type rowversion?

With Visual Basic in Visual Studio I am trying to select a row of type rowversion from a SQL Server database.
'version' is a column of type rowversion
SELECT [Version] FROM Employees WHERE Employee_id = 1
Then in VB - To get value from version column
Dim myBuffer As Byte()
Dim reader As SqlDataReader
numRead = reader.GetBytes(0, 0, myBuffer, 0, 16)
I know there is data in mybuffer from this:
For i = 0 To myBuffer.Length - 1
MsgBox(myBuffer(i).ToString())
Next
Also myBuffer.Length = 9
But when I want to query my database with myBuffer...
cmd.Parameters.AddWithValue("version", myBuffer)
I get the error:
Procedure or function 'updatePerson' expects parameter '#version', which was not supplied.
As if myBuffer in NULL.
Does anybody know to get the rowversion out of a database and then use it in a query?

LINQ to SQL anomaly

I'm trying to learn LINQ to SQL. I've run into something I just don't get. Here's the LINQ program (vb.net):
Imports System.IOModule Module1
Sub Main()
Dim crs = New DataClasses1DataContext()
Dim sw As New StringWriter()
crs.Log = sw
Dim reports = From report In crs.CRS_Report_Masters
Group report By report_id = report.Report_ID Into grouped = Group
Select New With {
.reportId = report_id,
.two = grouped.Sum(
Function(row) row.active_report * row.Report_ID)
}
For Each report In reports
Console.WriteLine("{0} {1}", report.reportId, report.two)
Next
MsgBox(sw.GetStringBuilder().ToString())
End Sub
End Module
Here's the SQL it produces:
SELECT SUM([t1].[value]) AS [two], [t1].[Report_ID] AS [reportId] FROM (
SELECT (-(CONVERT(Float,[t0].[active_report]))) *
(CONVERT(Float,CONVERT(Float,[t0].[Report_ID]))) AS [value], [t0].[Report_ID]
FROM [dbo].[CRS_Report_Master] AS [t0]
) AS [t1] GROUP BY [t1].[Report_ID]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
What I don't get is why there is a minus sign in the SQL before the math in the parentheses. I didn't specify that in the LINQ query.
If I recall correctly, VB.NET treats -1 as Boolean True, while SQL treats +1 as Boolean True. Therefore the minus sign is necessary for VB.NET to properly interpret the active_report field.
So, now I see what's going on. The LINQ to SQL definition of the column corresponding to a SQL bit is a .net Boolean. Fair enough. When doing math using it, however, the compiler negates the value as described by ekolis. I did not expect that -- in fact I think it's an error, since I do not get the results I expect. e.g. if active_report=1 and report_id=123, I expect to get "123" but I'm getting "-123". I modified the query like this:
Dim reports = (From report In crs.CRS_Report_Masters
Group report By report_id = report.Report_ID Into grouped = Group
Select New With {
.reportId = report_id,
.two = grouped.Sum(
Function(row) If(row.active_report, 1, 0) * CInt(row.Report_ID))
})
which changed the generated SQL to:
SELECT SUM([t1].[value]) AS [two], [t1].[Report_ID] AS [reportId] FROM (
SELECT (
(CASE
WHEN (COALESCE([t0].[active_report],#p0)) = 1 THEN #p1
ELSE #p2
END)) * (CONVERT(Int,[t0].[Report_ID])) AS [value], [t0].[Report_ID]
FROM [dbo].[CRS_Report_Master] AS [t0]
) AS [t1] GROUP BY [t1].[Report_ID]
-- #p0: Input Int (Size = -1; Prec = 0; Scale = 0) [0]
-- #p1: Input Int (Size = -1; Prec = 0; Scale = 0) [1]
-- #p2: Input Int (Size = -1; Prec = 0; Scale = 0) [0]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
Makes sense I suppose, though it's a roundabout way get the desired result. In T-SQL, a simple SELECT [BOOLEAN]*[INTEGER] will achieve the same result, I believe. Lesson learned: Don't trust LINQ to always do the right thing. Check its work!

Hibernate SQLQuery, how to get arrays and rows objects?

Hibernate 3.6 & postgresql 9.1.
Using SQLQuery how to get result array data (array of Long - assistants, array of rows of "Text, Long, Timestamp" - accounts)?
limit = 10000;
final SQLQuery sqlQuery = getSession().createSQLQuery("SELECT id, name, ts, " +
" array(SELECT assistant_id FROM user_assistant WHERE p_id=pr.id ORDER BY assistant_id) AS accounts," +
" array(SELECT row(type,uid,ts) FROM user_account WHERE p_id=pr.id ORDER BY type) AS accs," +
" FROM profile pr WHERE ts > ? ORDER BY ts LIMIT " + limit);
The most of DAO functions written with hibernate Entities & annotations.
But for a few statistics tasks easier to work with HQL or even SQL.
As opposed to pure JDBC in hibernateSQL working with arrays is not so intuitive.
JDBC could be a solution, but I haven't found any way to get JDBC Statement from Hibernate Session or Connection.
ResultTransformer doesn't help also, fails with:
org.hibernate.MappingException: No Dialect mapping for JDBC type: 2003
By referring this
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querysql.html
What you can do something like;
session.createSQLQuery("Your custom query")
.addScalar("field1", Hibernate.STRING)
.addScalar("field2", Hibernate.STRING)
.addScalar("field3", Hibernate.STRING)
and then
for(Object rows : query.list()){
Object[] row = (Object[]) rows;
String field1 = row[0] // contains field1
String field2 = row[1]
..
..
}

Entity Framework / SQL Server strange decimal division behaviour

I have a table in my SQL server 2008 R2 database which includes two nullable decimal(16,6) columns. Let's call them column1 and column2.
When I try to run a Linq query against the entity generated from this table:
Table.Select(r => new Foo
{
Bar = (r.Column1 + r.Column2) / 2m
}
);
I get a System.OverflowException if column1 + column2 >= 15846. The message of the exception is only:
Conversion overflows.
With a bit of trial and error I've managed to make the query work with the following:
Table.Select(r => new Foo
{
Bar = (r.Column1 + r.Column2).HasValue ?
(r.Column1 + r.Column2).Value / 2m : 0
}
);
However, I was wondering if anyone could explain what was going wrong with the initial query.
Edit
The first query generates this SQL:
SELECT
1 AS [C1],
([Extent1].[Column1] + [Extent1].[Column2]) / cast(2 as decimal(18)) AS [C2]
FROM [dbo].[Table] AS [Extent1]
With a value of 10000 for both columns, running the query manually in SSMS the result is 10000.0000000000000000000000000 (25 decimal zeros).
The second query has this SQL:
SELECT
1 AS [C1],
CASE WHEN ([Extent1].[Column1] + [Extent1].[Column2] IS NOT NULL)
THEN ([Extent1].[Column1] + [Extent1].[Column2]) / cast(2 as decimal(18))
ELSE cast(0 as decimal(18))
END AS [C2]
FROM [dbo].[Table] AS [Extent1]
Running the query in SSMS returns 10000.00000000000000000000 (20 decimal zeros). Apparently there is a problem when EF tries to convert the first value (with 25 decimal zeros) into a decimal but with the second (with 20 decimal zeros) it works.
In the meantime it turned out that the problem also occurs with non-nullable columns and even a single decimal(16, 6) column. The following ...
Table.Select(r => new Foo
{
Bar = r.Column1 / 2m
}
);
... throws the same conversion exception (with a value of 20000 in the Column1).
Why do those two SQL queries result in two different numbers of digits?
And why can't the first number be converted into a decimal by EF?

sql server date in the format yyyy-MM-ddThh:mm:ssZ

I need to format a set of dates in SQL server to the following format..
yyyy-MM-ddThh:mm:ssZ
I cant seem to find how to format the date with the T and Z parts included in the string
Any ideas how to achieve this format in a SQL query?
According to the SQL Server 2005 books online page on Cast and Convert you use date format 127 - as per the example below
CONVERT(varchar(50), DateValueField, 127)
SQL Server 2000 documentation makes no reference to this format - perhaps it is only available from versions 2005 and up.
Note on the time zone added to the end (from note 7 in the docs): The optional time zone indicator, Z, is used to make it easier to map XML datetime values that have time zone information to SQL Server datetime values that have no time zone. Z is the indicator for time zone UTC-0. Other time zones are indicated with HH:MM offset in the + or - direction. For example: 2006-12-12T23:45:12-08:00.
Thanks to Martin for this note: You should be able to use STUFF to remove the miliseconds as these will be in a fixed position from the left of the string. i.e.
SELECT STUFF(CONVERT(VARCHAR(50),GETDATE(), 127) ,20,4,'')
DECLARE #SampleDate DATETIME2(3) = '2020-07-05 23:59:59';
SELECT CONVERT(VARCHAR(20), CONVERT(DATETIMEOFFSET, #SampleDate), 127);
--results: 2020-07-05T23:59:59Z
You can parse C# output in SQL using below:
SELECT CONVERT(DATETIME, CONVERT(DATETIMEOFFSET,'2017-10-27T10:44:46Z'))
Use C# to generate this using the following:
string ConnectionString = "Data Source=SERVERNAME; Initial Catalog=DATABASENAME; Persist Security Info=True; User ID=USERNAME; Password=PASSWORD";
using(SqlConnection conn = new SqlConnection(ConnectionString))
{
DateTime d = DateTime.Now;
string Query = "SELECT CONVERT(DATETIME, CONVERT(DATETIMEOFFSET,'" + d.ToString("yyyy-MM-dd") + "T" + d.ToString("HH:mm:ss") + "Z'))"
conn.Open();
using(SqlCommand cmd = new SqlCommand(Query, conn))
{
using(SqlDataReader rdr = cmd.ExecuteReader())
{
if(rdr.HasRows)
{
while(rdr.Read())
{
for(int i; i < rdr.length; i++)
{
Console.WriteLine(rdr[0].ToString());
}
}
//DataTable dt = new DataTable(); dt.Load(rdr); //Alternative method if DataTable preferred
}
}
}
}
select left(convert(varchar(30),getdate(),126)+ '.000',23)
Try this
SELECT STUFF(
CONVERT(datetime2(0), GETDATE(), 126)
AT TIME ZONE 'US Eastern Standard Time'
,11,1,'T')
on MSSQL
SELECT FORMAT( GETDATE(),'yyyy-MM-ddTHH:mm:ss.ms zzzz')

Resources