Tree View Query - sql

I created a query to get all addresses(child) with in municipality(parent) but it is coming back empty/ Any help is appreciated.
drop table #tmp1
go
WITH Emp_CTE AS (
SELECT tablesysID, MunicNo, StreetName
FROM table1
UNION ALL
SELECT e.tablesysID,e.MunicNo,e.StreetName
FROM table1 e
INNER JOIN Emp_CTE ecte ON ecte.MunicNo = e.MunicNo
)
SELECT * into #tmp1
FROM Emp_CTE
select * from #tmp1
it will be used in asp.net tree view control.
Thanks Andomar for your answer, which is correct but I just wanted to share how I solved this problem as follows:
1: make the query as stored procedure that returns xml data type as response like:
create PROCEDURE [dbo].[sp_someproc]
#XmlResponse xml output
AS
BEGIN
--
-- Insert statements for procedure here
set #XmlResponse=(SELECT DISTINCT
table1.MunicNo + ' ' + table1.StreetName + ' ' + table1.City AS firstRow, table1.MunicNo, table1.StreetName, table1.City,
table1.XPOS, table1.YPOS, table1.RollID, table2.Asset_ID, table2.Feature_ID, table2.FeatureName + ',' + table2.Feature_ID + ' ' + table2.[DESC] AS secondRow,
table2.FeatureName, table2.xxxID, table2.[DESC],table3.WONOs, table3.WONOs + ', ' + table3.AssetType + ', ' +table3.Feature_ID AS workONumber
FROM table4 INNER JOIN
table3 ON table4.xxxxID = table3.xxxxID INNER JOIN
table2 ON table4.Asset_ID = table2.xxx_ID INNER JOIN
table1 ON table2.StreetName = table1.StreetName AND table3.MunicNo = table1.MunicNo
for xml auto,root('xml'))
END
select #XmlResponse
2: Aspx page code:
<telerik:RadTreeView ID="rtrvxxxxx" runat="server" >
<DataBindings>
<telerik:RadTreeNodeBinding DataMember="table1" TextField="firstRow" ValueField="firstRow" />
<telerik:RadTreeNodeBinding DataMember="table2" TextField="secondRow" />
<telerik:RadTreeNodeBinding DataMember="table3" TextField="workONumber" />
</DataBindings>
</telerik:RadTreeView>
3: C# Code:
private void loadXmlDocument()
{
try
{
#region Load and Bind xml to treeview
XmlDataSource xDS = new XmlDataSource();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc = callingdatalayerclass.list_XML();
xDS.Data = xmlDoc.InnerXml;
xDS.XPath = "/xml/table1";
xDS.EnableCaching = false;
//bind to treeview
rtrvxxxx.DataSource = xDS;
rtrvxxxx.DataBind();
#endregion
}
catch (Exception ex)
{
ex.Message()}
}
}
4: Data access Layer Code:
public static XmlDocument List_XML()
{
XmlDocument xmlDoc = new XmlDocument();
SqlConnection SQLConn = new SqlConnection();
SQLConn.ConnectionString = someclass.someotherclass.GetConnectionString();
try
{
SQLConn.Open();
SqlCommand custCMD = new SqlCommand("sp_someproc", SQLConn);
custCMD.CommandType = CommandType.StoredProcedure;
custCMD.Parameters.Add("#XmlResponse", SqlDbType.Xml).Direction = ParameterDirection.Output;
custCMD.ExecuteNonQuery();
if (custCMD.Parameters["#XmlResponse"].Value != null)
{
string xml = custCMD.Parameters["#XmlResponse"].Value.ToString();
xmlDoc.LoadXml(xml);
}
return xmlDoc;
}
catch (Exception exGEN)
{
throw exGEN;
}
finally
{
SQLConn.Close();
}
}
Notes: if you see query has rows those are first layer of treeview and 2ndrow is inner row of 1st row or can call it a child of parentnode, 3rd row is inner row or child row of 2nd row, so if 1st row has some records it will output that, if 2nd row has some reocrds it will ouput that. if you see the databining section in treeview datamember is table name and
textfiled is firstrow, value field could be some other coulmn. Have not worked with asp.net orginal treeview so don't know how that works this is for telerik treeview control. I also found that the speed is way faster if data is slected as xml. "DS.XPath = "/xml/table1";" <= this code is selecting xml element or root element and then with in that element the first element which by the data is sorted(first row record's table)

Have a look at your recursive condition:
INNER JOIN Emp_CTE ecte ON ecte.MunicNo = e.MunicNo
This recurses into the same municipality. (Except when MinicNo is null.)
You haven't posted enough information to find the proper condition, but it might look like:
INNER JOIN Emp_CTE ecte ON ecte.tablesysID = e.MunicNo

Related

How to use SQL Raw query in ASP .Net MVC web api

My Connection String:
<add name="addConnection" connectionString="Data Source=(LocalDb)\v11.0;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\FLWorkDB.mdf" providerName="System.Data.SqlClient" />
<add name="FLWorkDBEntities" connectionString="metadata=res://*/MyEdmx.csdl|res://*/MyEdmx.ssdl|res://*/MyEdmx.msl;provider=System.Data.SqlClient;provider connection string="data source=(LocalDB)\v11.0;attachdbfilename=|DataDirectory|\FLWorkDB.mdf;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
My Web API:
[HttpGet]
[Route("api/JobApi/BrowseJobs/")]
public object BrowseJobs()
{
using (var ctx = new FLWorkDBEntities())
{
//Get student name of string type
object studentName = ctx.Database.SqlQuery<string>(#"Select j.JobID,j.JobDetails,j.JobTitle, j.Deadline ,j.Budget,j.Category, emp.FirstName,emp.LastName,Skills = Stuff((Select ',' +SkillName From Skill Where charindex(concat(',',SkillID,','),','+j.ReqSkill+',')>0 For XML Path ('')),1,1,'')
From Job j
join Employeer emp on j.EmployeerID = emp.EmployeerID
WHERE NOT EXISTS
(SELECT *
FROM ClosedJob c
WHERE c.JobID = j.JobID) AND
NOT EXISTS
(SELECT *
FROM AppliedJob apj
join JobOffer jo on apj.AppliedJobID =jo.AppliedJobID
join Contract con on jo.OfferID =con.OfferID
WHERE con.CompletedDate != Null)").ToList();
}
return stu;
}
Now i am doing all with LINQ. But i want to avoid LINQ and add direct sql query.
RAW Sql: "Select * from A where A.ID =2"(with join)
I want to add the RAW SQL Query in my web api that returns list in json.
Can i add sql query without entity framework, i mean .edmx file?
Edited==============
Tried this:
var results = db.Database.SqlQuery<FLWorkDBEntities>(#"Select j.JobID,j.JobDetails,j.JobTitle, j.Deadline ,j.Budget,j.Category, emp.FirstName,emp.LastName,Skills = Stuff((Select ',' +SkillName
From Skill
Where charindex(concat(',',SkillID,','),','+j.ReqSkill+',')>0
For XML Path ('')),1,1,'')
From Job j
join Employeer emp on j.EmployeerID = emp.EmployeerID
WHERE NOT EXISTS
(SELECT *
FROM ClosedJob c
WHERE c.JobID = j.JobID) AND
NOT EXISTS
(SELECT *
FROM AppliedJob apj
join JobOffer jo on apj.AppliedJobID =jo.AppliedJobID
join Contract con on jo.OfferID =con.OfferID
WHERE con.CompletedDate != Null)").ToList<FLWorkDBEntities>();
return JsonConvert.SerializeObject(results);
But returns:
Self referencing loop detected with type 'System.Data.Entity.DynamicProxie
================Solved====================
I made a stored procedure (BrowseJobs) then attached it with the following code
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["addConnection"].ConnectionString);
SqlCommand com = new SqlCommand("BrowseJobs", con);
com.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter(com);
DataSet ds = new DataSet();
da.Fill(ds);
return ds.Tables[0];
Yes. You can go through this link http://www.entityframeworktutorial.net/EntityFramework4.3/raw-sql-query-in-entity-framework.aspx
E.g.;
using (var context = new SqlDbContext())
{
//Get command for non entity types
string studentName = context.Database.SqlQuery<string>(#"SELECT StudentName FROM Student WHERE StudentID = 1").FirstOrDefault<string>();
//Get command for entity types. SQL columns returned by SQL query should match the property of the entity type
var students = context.Students.SqlQuery(#"SELECT * FROM Student").ToList<Student>();
//Update command
int noOfRowsUpdated = context.Database.ExecuteSqlCommand(#"UPDATE Student SET StudentName = 'New Name' WHERE StudentID = 1");
//Insert command
int noOfRowsInserted = context.Database.ExecuteSqlCommand(#"INSERT INTO Student(StudentName) VALUES('New Student')");
//Delete command
int noOfRowsDeleted = context.Database.ExecuteSqlCommand(#"DELETE FROM Student WHERE StudentID = 1");
}
You can return the list in JSON format using Newtonsoft.Json. Just follow these steps:
PM> Install-Package Newtonsoft.Json
using Newtonsoft.Json;
var jsonResult = JsonConvert.SerializeObject(students);
You can do this in entity framework.
The documentation link : https://msdn.microsoft.com/en-us/library/jj592907(v=vs.113).aspx
example link : http://www.entityframeworktutorial.net/EntityFramework4.3/raw-sql-query-in-entity-framework.aspx
To, do it without edmx then use old ado.net.

Converting comma-separated value to in subquery

I have following query :
Set #OrderStatuses = 'Cancelled,Complete'
Select *
From TableName
Where Status in (#OrderStatuses)
The Status is what I am receiving externally and it fails to fetch any result as, what we actually need to process is:
Select *
From TableName
Where Status in ('Cancelled', 'Complete');
#OrderStatuses can contain any number of comma-separated values.
One method is dynamic SQL:
declare #sql nvarchar(max);
set #sql = 'Select * from TableName Where Status in (#list)';
set #sql = replace(#sql, '#list', '#OrderStatuses');
exec sp_executesql #sql;
Note: You cannot pass a list in as a parameter.
You can also use like:
Select *
from TableName
Where ',' + #OrderStatuses + ',' like '%,' + Status + ',%';
However, this cannot use an index for the the comparison.
You will need to use split string function and process the rest..
;with cte
as
(
select * from split_strings(#orderstatus,',')
)
select * from table where status in (select item from cte)
You must add the list as a Table-Valued Parameter
Here are two methods I use to convert any IEnumerable list of items (in this case, integers) into a Table Valued Parameter. You have to have created/defined a User Defined type (UDT) for the resultant table in your database. In the example below the UDT is named dbo.keyIds and is created (once) with this SQL:
CREATE TYPE [dbo].[KeyIds]
AS TABLE(pkId int NOT NULL, PRIMARY KEY CLUSTERED
( [pkId] ASC) WITH (IGNORE_DUP_KEY = OFF)
)
The c# code is:
public class DbParamList : List<IDbDataParameter>
{
public void AddSQLTableParm<T>(
string parmName, IEnumerable<T> values)
{
var parm = new SqlParameter(parmName, CreateDataTable(values))
{
SqlDbType = SqlDbType.Structured,
TypeName = "dbo.keyIds"
};
Add(parm);
}
internal static DataTable CreateDataTable<T>(IEnumerable<T> values)
{
var dt = new DataTable();
var props = typeof (T).GetProperties();
if (props.Length > 0)
{
foreach (var col in props)
dt.Columns.Add(col.Name, col.PropertyType);
foreach (var id in values)
{
var newRow = dt.NewRow();
foreach (var prop in id.GetType().GetProperties())
newRow[prop.Name] = prop.GetValue(id, null);
dt.Rows.Add(newRow);
}
}
else
{
dt.Columns.Add("ids");
foreach (var id in values) dt.Rows.Add(id);
}
return dt;
}
}

MS SQL Query in C# - poor performance

I calculate outstanding customers balance in C# Winforms. The code below works, but it's slow. Is there any way to improve its performance?
public DataTable GetOutStandingCustomers()
{
decimal Tot = 0;
DataTable table = new DataTable();
SqlConnection con = null;
try
{
table.Columns.Add("Code", typeof(Int32));
table.Columns.Add("Name", typeof(string));
table.Columns.Add("City", typeof(string));
table.Columns.Add("Tot", typeof(decimal));
string constr = ConfigHelper.GetConnectionString();
string query = "SELECT Code, Name,City FROM Chart WHERE LEFT(CODE,3)='401' AND Code > 401001 ";
string query0 = " SELECT(SELECT ISNULL( SUM(SalSum.Grand),'0' ) FROM SalSum WHERE SalSum.Code = #Code ) +( SELECT ISNULL(SUM(Journals.Amount),'0' ) FROM Journals WHERE Journals.DrCode = #Code ) -( SELECT ISNULL(SUM(RSalSum.Grand),'0' ) FROM RSalSum WHERE RSalSum.Code = #Code ) -( SELECT ISNULL(SUM(Journals.Amount),'0' ) FROM Journals WHERE Journals.CrCode = #Code )+(SELECT ISNULL(SUM(Chart.Debit),'0' ) FROM Chart WHERE Chart.Code = #Code) - (SELECT ISNULL(SUM(Chart.Credit), '0') FROM Chart WHERE Chart.Code = #Code)";
Person per = new Person();
con = new SqlConnection(constr);
SqlCommand com = new SqlCommand(query, con);
SqlCommand com0 = new SqlCommand(query0, con);
con.Open();
SqlDataReader r = com.ExecuteReader();
if (r.HasRows)
{
while (r.Read())
{
per.Name = Convert.ToString(r["Name"]);
per.City = Convert.ToString(r["City"]);
per.Code = Convert.ToString(r["Code"]);
com0.Parameters.Clear();
com0.Parameters.Add("#Code", SqlDbType.Int).Value = per.Code;
Tot = Convert.ToDecimal(com0.ExecuteScalar());
if (Tot != 0)
{
table.Rows.Add(per.Code, per.Name, per.City, Tot);
}
}
}
r.Close();
con.Close();
return table;
}
catch (Exception)
{
throw new Exception();
}
}
The performance problem is due to you retrieve all data from the server and filter data in the client using the complex computed expression that sum from seven tables:
if (Tot != 0)
{
table.Rows.Add(per.Code, per.Name, per.City, Tot);
}
This represent overhead over network plus you manually add the result to the datatable row by row.
The provided solution do filter in the server based on the computed expression using the CROSS APPLY
and auto create the datatable directly from the DataReader.
The benefit of CROSS APPLY is all columns are feasible to the main sql query, so you can filter on ToT column, filtering is done in the server (not the client).
public void SelctChart()
{
string sql2 = #"
select c.Code, c.Name,c.City ,oo.T
from chart c
cross apply
( select c.code,
(
(select ISNULL( SUM(SalSum.Grand),0 ) FROM SalSum WHERE SalSum.Code = c.code )
+( select ISNULL(SUM(j.Amount),0 ) FROM [dbo].[Jornals] j WHERE j.DrCode = c.code)
-( SELECT ISNULL(SUM(RSalSum.Grand),'0' ) FROM RSalSum WHERE RSalSum.Code = c.Code )
-( SELECT ISNULL(SUM(j.Amount),0 ) FROM [dbo].[Jornals] j WHERE j.CrCode = c.code )
+(SELECT ISNULL(SUM( c0.Debit),0 ) FROM [dbo].Chart c0 WHERE c0.Code = c.code)
- (SELECT ISNULL(SUM(c1.Credit), 0) FROM [dbo].Chart c1 WHERE c1.Code = c.code)
)T
) oo
where
oo.T >0
and LEFT(c.CODE,3)='401' AND c.Code > 401001
";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(sql2, connection);
//in case you pass #code as a a parameter
//command.Parameters.Add("#code", SqlDbType.Int);
//command.Parameters["#code"].Value = code;
try
{
connection.Open();
var reader = command.ExecuteReader();
while (!reader.IsClosed)
{
DataTable dt = new DataTable();
// Autoload datatable
dt.Load(reader);
Console.WriteLine(dt.Rows.Count);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
You can modify the method and pass code as a parameter
In this case it seems you're looping through and performing multiple queries using multiple Codes, you're also querying Chart twice. In this case you'd want to use a LEFT JOIN from Chart to your other tables.
ON Chart.Code = Salsum.Code
ON Chart.Code = Journal.Code
for example.
You will have to look at GROUP BY as well because you're aggregating some table columns by using SUM.
You may also need to make sure that Code is indexed on the tables you're querying. As long as Code is often queried like this and comparatively rarely Updated or Inserted to, then indexing the Code column on these tables is probably appropriate.
Left Joins : https://technet.microsoft.com/en-us/library/ms187518(v=sql.105).aspx
Indexing: https://technet.microsoft.com/en-us/library/jj835095(v=sql.110).aspx
Sorry I wrote a book on you here, but optimization often leads to a long answer (especially with SQL).
tldr;
Use a LEFT JOIN, grouping by Code
Index the Code columns

Can we set static value at the end of Dropdown list?

I am having two Drop Down list Country and state both list are filled from database. In Drop Down list for states I want to add "Others" at the end of the list. I tried adding "Others" from database but when I use order by Name to show name of states in alphabetic order in my Drop Down List even "Other" gets rearranged but I want to display it at the end of my list.
This is my code how I am populating my list
private void FillStateDDl()
{
DataSet ds = new DataSet();
try
{
SqlParameter[] sql = new SqlParameter[2];
sql[0] = new SqlParameter("#Type", 2);
sql[1] = new SqlParameter("#cid", drpCountry.SelectedValue);
ds = gs.DisplayData("sp_FillDropDownList", sql);
if (ds.Tables[0].Rows.Count > 0)
{
drpState.DataTextField = "statename";
drpState.DataValueField = "sid";
drpState.DataSource = ds;
drpState.DataBind();
drpState.Items.Insert(0, new ListItem("--Select State--", "-1"));
}
}
catch (Exception ex)
{
Response.Write(ex.Message.ToString());
}
}
You need to ensure that AppendDataBoundItems is set to true.
Then items can be added after the data source like:
ddl.AppendDataBoundItems = true;
ddl.DataSource = CreateDataSource();
ddl.DataTextField="TextField";
ddl.DataValueField="ValueField";
ddl.DataBind();
ddl.Items.Add("Static value here....");
Yes, you can set static value with datasource in the dropdown list. You need to do following steps:
Select properties of dropdownlist, and find AppendDataBoundItems and set AppendDataBoundItems = true.
After binding the dropdown list, add following line of code ddl.Items.Add("Others") in vb.net
Also order by in descending order
In SQL you can do something like this
;WITH C AS(
SELECT 1 AS RowId, .... -- Main query
UNION ALL
SELECT 2 AS RowId, ... -- Include others here
)
SELECT * FROM C
ORDER BY RowId
Try this,
drpState.Items.Insert(drpState.Items.Count - 1, new ListItem("--Select State--", "-1"));

How to Join two tables showing all records Where Table A is Not In Table B

I have a email marketing web application. I want to show which email contacts in (Table B) are not showing up in EmailContacts_Campaign (Table A). In addition, I want to filter table A by the CampaignId field. When I run the below code I get 0 records, yet I know there are a couple of thousand records there. Can anyone tell me where I am messing up?
SELECT * FROM TableA
LEFT JOIN TableB
ON TableA.EmailContactId = TableB.EmailContactId
WHERE TableA.CampaignId = 1
AND TableB.EmailContactId IS NULL
ORDER BY TableB.EmailContactId DESC
I want to show all email contacts in the EmailContact Table that are not showing up in the EmailContactCampaign table. Here is the actual code:
public List<EmailContact> GetNotAssignedContactsForCampaign(int campaignId)
{
string sqlCommand = "SELECT * FROM EmailContactCampaign LEFT JOIN EmailContact";
sqlCommand += " ON EmailContactCampaign.EmailContact_EmailContactId = EmailContact.EmailContactId";
sqlCommand += " WHERE EmailContactCampaign.EmailContact_EmailContactId = " + campaignId.ToString() AND EmailContact.EmailContactId IS NULL ;
sqlCommand += " ORDER BY EmailContact.EmailContactId DESC";
var emailContacts = new List<EmailContact>();
string CS = db.Database.Connection.ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
{
con.Open();
SqlCommand cmd = new SqlCommand(sqlCommand, con);
//Create sql datareader
using (SqlDataReader sqlDataReader = cmd.ExecuteReader())
{
while (sqlDataReader.Read())
{
var emailContact = new EmailContact();
emailContact.Assigned = ((bool)sqlDataReader["Assigned"]);
emailContact.Cell1 = _crypto.DecryptAndSanitize(sqlDataReader["Cell1"] as string);
emailContact.Cell2 = _crypto.DecryptAndSanitize(sqlDataReader["Cell2"] as string);
emailContact.City = _crypto.DecryptAndSanitize(sqlDataReader["City"] as string);
emailContact.Company = _crypto.DecryptAndSanitize(sqlDataReader["Company"] as string);
emailContact.EmailAddress = _crypto.DecryptAndSanitize(sqlDataReader["EmailAddress"] as string);
emailContact.EmailContactId = (int)sqlDataReader["EmailContactId"];
emailContact.FullName = _crypto.DecryptAndSanitize(sqlDataReader["FullName"] as string);
emailContact.Hold = (bool)sqlDataReader["Hold"];
emailContact.Phone1 = _crypto.DecryptAndSanitize(sqlDataReader["Phone1"] as string);
emailContact.Phone2 = _crypto.DecryptAndSanitize(sqlDataReader["Phone2"] as string);
emailContact.State = _crypto.DecryptAndSanitize(sqlDataReader["State"] as string);
emailContact.Status = (Status)sqlDataReader["Status"];
emailContact.Zip = _crypto.DecryptAndSanitize(sqlDataReader["Zip"] as string);
emailContacts.Add(emailContact);
}
}
return (emailContacts);
}
}
Have you tried this?
SELECT * FROM tableB WHERE EmailContactId NOT IN (SELECT EmailContactId FROM tableA)
i think you got 0 probably because of this AND TableB.EmailContactId IS NULL
Please try this one
SELECT * FROM TableA
LEFT JOIN TableB
ON TableA.EmailContactId = TableB.EmailContactId
WHERE TableA.CampaignId = 1
ORDER BY TableB.EmailContactId DESC
I'm sorry my question was not clear enough. Did some digging and found the answer on another post. Sorry but I accidentally closed it and can't find it again. Anyway, here is my implementation of it.
SELECT * FROM EmailContact
WHERE NOT EXISTS
(SELECT * FROM EmailContactCampaign WHERE EmailContactCampaign.EmailContact_EmailContactId = EmailContact.EmailContactId AND EmailContactCampaign.Campaign_CampaignId = 1)
If i understood your question correctly, you are looking for B's that are not in A. But your query will return A's that are not in B. Turn it aroung (tableB left join tableA where a... is NULL)
Your problem was that you had it the wrong way around: your query would return all contacts from EmailContactCampaign that were not in EmailContact.
The correct solution for your problem would look like this:
SELECT * FROM EmailContact
WHERE EmailContactId NOT IN (
SELECT EmailContact_EmailContactId FROM EmailContactCampaign
WHERE Campaign_CampaignId = ?
)
ORDER BY EmailContact.EmailContactId DESC