Syntax for inner Join query for 4 table - c#

I want to get the data from my access database and show the data at Datagridview. my tables are:
TABLE 1(AB) TABLE 2(CD) TABLE 3(EF) TABLE 4(GH)
------------- ----------------- ------------- -------------------
SID SName CID TID TID TName Tprice FID CID FCp FPID FID FCp Fprice
The query which I am using to retrieve the data in C# is:
OleDbCommand command1 = new OleDbCommand();
command1.Connection = connection;
command1.CommandText = "select T.TName, T.Tprice, P.FCp, P.Fprice from (([AB] S inner join [CD] T on S.TID = T.TID) (inner join [EF] C on S.CID = C.CID) inner join [GH] P on C.FID = P.FID where (S.SID = 2) ";
OleDbDataReader myreader = command1.ExecuteReader();
while (myreader.Read())
{
//DATA IS READ HERE
}
The error which I am getting is:
Syntax error at JOIN expression
I want TName, Tprice, FCp(TABLE 4), Fprice as my output. Am I doing it right or is there any other way to do that.

In your from you have opening parentheses with no closing (the first one).
Besides fixing the parentheses it is much more readable if you jump lines:
command1.CommandText = #"select T.TName, T.Tprice, P.FCp, P.Fprice
from (([AB] S
inner join [CD] T on S.TID = T.TID)
inner join [EF] C on S.CID = C.CID)
inner join [GH] P on C.FID = P.FID
where S.SID = 2";
(Access requires parentheseses)

Related

Asp.NET C# MVC - How show the result a query with multiples table

I'm executing the following code:
public ActionResult BranchUser(int ? idBranch)
{
CtrForm objCtrForm = new CtrForm();
objCtrForm.Connect();
objCtrForm.query.Connection = objCtrForm.connection;
objCtrForm.query.CommandType = CommandType.Text;
List<tblUser> listBranchUser = new List<tblUser>();
string sql = #"SELECT B.name, B.phone, B.email, B.idUser FROM tblBranchUser A
INNER JOIN tblUsers B ON A.idUser = B.idUser
WHERE A.idBranch = " + idBranch;
objCtrForm.query.CommandText = sql;
objCtrForm.connection.Open();
SqlDataReader sReader = objCtrForm.query.ExecuteReader();
while (sReader.Read())
{
listBranchUser.Add(
new tblUser
{
idUser = Convert.ToInt32(sReader["idUser"]),
name = Convert.ToString(sReader["name"]),
phone = Convert.ToString(sReader["phone"]),
email = Convert.ToString(sReader["email"])
}
);
}
objCtrForm.connection.Close();
return View(listBranchUser);
}
but I got the following error when I call the function:
System.Data.SqlClient.SqlException: 'Incorrect syntax near '='.'
I don't understand why I get this, due to I executed in other functions but I only called one table, not two. Any advice I will appreciate.
I believe C# won't implicitly convert an integer to a string.
Try replacing
string sql = #"SELECT B.name, B.phone, B.email, B.idUser FROM tblBranchUser A
INNER JOIN tblUsers B ON A.idUser = B.idUser
WHERE A.idBranch = " + idBranch;
With
string sql = #"SELECT B.name, B.phone, B.email, B.idUser FROM tblBranchUser A
INNER JOIN tblUsers B ON A.idUser = B.idUser
WHERE A.idBranch = " + idBranch.ToString();

Select Query Parameter from C# in a stored procedure

How does a SQL Server query select from parameter? I just want to make it simple set select column based on my C# code. Is it possible?
Here is my stored procedure:
ALTER PROCEDURE [dbo].[GetMembersDetailGenerateChanceTop10000]
#EventId nvarchar(255),
#PeriodId nvarchar(255),
#QueryParam nvarchar(1000)
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT TOP 10000 #QueryParam
FROM ign..Chance_Generated cg
INNER JOIN ign..Contact c ON cg.ContactID = c.ContactId
LEFT JOIN ign..CustomerAddress ca ON ca.parentid = cg.contactid
LEFT JOIN ign..new_cardlevelconfig cl ON cl.new_cardlevelconfigid = c.new_cardlevel
LEFT JOIN ign..new_country co ON co.new_countryid = c.new_country
LEFT JOIN ign..new_province po ON po.new_provinceId = c.new_Province
LEFT JOIN ign..StringMap sm ON sm.AttributeValue = c.new_IDType
LEFT JOIN ign..new_city cy ON cy.new_cityId = c.new_CityCounty
LEFT JOIN ign..new_transactionheader th ON cg.New_Name COLLATE DATABASE_DEFAULT = th.new_name COLLATE DATABASE_DEFAULT
WHERE cg.EventId = #EventId
AND (ca.AddressNumber = '1' OR ca.AddressNumber IS NULL)
AND (sm.AttributeName IS NULL OR sm.AttributeName = 'new_idtype')
AND cg.periodId = #PeriodId
QueryParam, EventId, PeriodId will be filled from C# code.
Here is my C# code:
private List<GenerateModel> getDataTopFromStoreProcedure(string EventId, string PeriodId)
{
// query select parameter
string QueryParam = #"cg.Chance_Number, th.new_name as [th name], dateadd(HOUR,7,th.createdon) as [th createdon],
c.new_Initial, c.FirstName, c.LastName";
string ConnString = GenerateChance.Properties.Settings.Default["DB_ConnectionString"].ToString();
using (SqlConnection conn = new SqlConnection(ConnString))
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = GetMembersDetailGenerateChanceTop10000;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0; //no limit
cmd.Parameters.Clear();
cmd.Parameters.Add(new SqlParameter("QueryParam", QueryParam));
cmd.Parameters.Add(new SqlParameter("EventId", EventId));
cmd.Parameters.Add(new SqlParameter("PeriodId", PeriodId));
cmd.Connection = conn;
if (conn.State == ConnectionState.Open)
conn.Close();
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
list.Add(new GenerateModel
{
ChanceNumber = reader["Chance_Number"].ToString(), //System.IndexOutOfRangeException Error
Receipt = reader["th name"].ToString(),
Date = reader["th createdon"].ToString(),
Initial = reader["new_Initial"].ToString(),
FirstName = reader["FirstName"].ToString(),
LastName = reader["LastName"].ToString(),
});
}
reader.Close();
}
}
return list;
}
I am confused as to how to implement his method because I want to get return of all select results in object model but I always get error
System.IndexOutOfRangeException : Chance_Number.
Honestly why do I use query select parameter is because I want to get value from checkedListBox1 that already I defined before by using this code get all checkedListBox1 value to determine select query.
string QueryParam = "cg.Chance_Number";//auto get chance_number as select mandatory
for (int i = 0; i < checkedListBox1.CheckedItems.Count; i++)
{
QueryParam += ", " + ((clsItemList)checkedListBox1.CheckedItems[i]).Value;
}
You have to use constructor with proper length for parameters as given below, to avoid the issue.Read more on SQLParameter
public SqlParameter (string parameterName, System.Data.SqlDbType dbType, int size);
cmd.Parameters.Add(new SqlParameter("QueryParam", SqlDbType.NVarChar,1000)).Value = QueryParam;
You need to make few more changes:
The way you have defined the procedure is wrong. You have to define the procedure as dynamic sql for the #queryparam to get concatenated to the SELECT query as given below:
DECLARE #selectStmt NVARCHAR(MAX) = ''
DECLARE #sqldefinition NVARCHAR(4000) = '#EventId nvarchar(255), #PeriodId nvarchar(255)'
SET #selectStmt += 'select distinct top 10000 ' + #QueryParam +
'from ign..Chance_Generated cg
inner join ign..Contact c on cg.ContactID = c.ContactId
left join ign..CustomerAddress ca on ca.parentid = cg.contactid
left join ign..new_cardlevelconfig cl on cl.new_cardlevelconfigid = c.new_cardlevel
left join ign..new_country co on co.new_countryid = c.new_country
left join ign..new_province po on po.new_provinceId = c.new_Province
left join ign..StringMap sm on sm.AttributeValue = c.new_IDType
left join ign..new_city cy on cy.new_cityId = c.new_CityCounty
left join ign..new_transactionheader th on cg.New_Name COLLATE DATABASE_DEFAULT = th.new_name COLLATE DATABASE_DEFAULT
where cg.EventId= '''+ #EventId +''' and (ca.AddressNumber = ''1'' or ca.AddressNumber is null) and (sm.AttributeName is null or sm.AttributeName = ''new_idtype'')
and cg.periodId = ''' + #PeriodId + ''';'
EXEC #sp_executesql #selectStmt, #sqldefinition, #EventId , #PeriodId
``
- Always refer the tables with proper schema in the query
ign.SchemaName.new_country
ign.SchemaName.new_province

How to count how many customers have purchase a product in SQL

I have a C# application that displays products that a company sells. Next to that column is the product type and in the last column is the number of customers that have bought that product. This is my SQL query to populate the first two columns:
string selectQuery;
selectQuery = "SELECT Products.ProductID, Products.ProductTypeID, ";
selectQuery = selectQuery + "Products.ProductName, Products.YearlyPremium, ProductTypes.ProductType ";
selectQuery = selectQuery + "FROM Products ";
selectQuery = selectQuery + "INNER JOIN ProductTypes ON Products.ProductTypeID = ProductTypes.ProductTypeID "
Now I need to work out how many customers bought each product. I guess I need to use the COUNT(*) method to get CustomerID's but now sure how to integrate it into this query.
Here is the schema
The code I use to display the data in the listView is this:
SqlConnection conn = ConnectionsManager.DatabaseConnection();
SqlDataReader rdr = null;
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(selectQuery, conn);
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Products product = new Products(int.Parse(rdr["ProductID"].ToString()),
int.Parse(rdr["ProductTypeID"].ToString()),
rdr["ProductName"].ToString(),
Math.Round(decimal.Parse(rdr["YearlyPremium"].ToString()), 2));
ProductTypes productType = new ProductTypes(int.Parse(rdr["ProductTypeID"].ToString()),
rdr["ProductType"].ToString());
ListViewItem lvi = new ListViewItem(product.ProductName.ToString());
lvi.SubItems.Add(productType.ProductType.ToString());
\\lvi.SubItems.Add(customer.CustomerID.ToString()); <---this will be the line to display the customer count
lvMain.Items.Add(lvi);
}
if (rdr != null)
rdr.Close();
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show("Unsuccessful" + ex);
}
Considering that ProductTypeId is has to be a NON NULL value in final result (hence using INNER JOIN), the SQL part which you will have to embed in your C# code:
SELECT P.ProductID, P.ProductTypeID, P.ProductName, P.YearlyPremium, PT.ProductType, CustomerCount = COUNT(S.CustomerID)
FROM Sales S
INNER JOIN Products P
ON S.ProductID = P.ProductID
INNER JOIN ProductTypes PT
ON P.ProductTypeID = PT.ProductTypeID
GROUP BY P.ProductID, P.ProductTypeID, P.ProductName, P.YearlyPremium, PT.ProductType
Note:- Since you do not need any attribute of the customer, and you have a foreign key on Sales.CustomerID column to Customer.CustomerId column, hence for the purpose of getting the CustomerCount, join to Customer table is not necessary.
You would seem to want a basic GROUP BY query:
SELECT p.ProductID, p.ProductTypeID, p.ProductName, p.YearlyPremium,
pt.ProductType,
COUNT(DISTINCT s.CustomerID) as num_customers
FROM Products p INNER JOIN
ProductTypes pt
ON p.ProductTypeID = PT.ProductTypeID LEFT JOIN
Sales S
ON s.ProductID = p.ProductID
GROUP BY p.ProductID, p.ProductTypeID, p.ProductName, p.YearlyPremium, pt.ProductType;
Notes:
This uses a LEFT JOIN to Sales to get products that have no sales.
This uses an INNER JOIN to ProductTypes because, presumably, all products have a type.
The GROUP BY has all non-aggregated columns.
This counts unique customer ids, because the same customer may have purchased the same product on more than one occasion. If you just want a count of the records in Sales, remove the DISTINCT.
try using Group by clause. It will work.
Example:
SELECT COUNT(ProductId),CustomerId
FROM Product
GROUP BY CustomerId;
kind of this

Inner join statement in bind variables

I use bind variables to get data from the SQL tables.
The code:
string commandText = string.Format("SELECT {0} FROM {1} WHERE {2} ORDER BY {3}", fields, from, whereStr, orderBy);
DbCommand command = GetSqlCommandWrapper(commandText);
int index = 0;
foreach (var item in whereParams)
{
command.Parameters.Add(new OracleParameter(item, whereParamsBy[index++]));
}
DataTable db = new DataTable();
DataSet dataSet = null;
dataSet = CurrentDatabase.ExecuteDataSet(command);
The CommandText:
fields = "TableA.*";
from = "TableA INNER JOIN TableB ON TableA .id = TableB.id";
whereStr = "TableA .id > 10";
orderBy = "TableA .id, TableB .id";
Everything works fine until I have to get data from 2 tables like the query:
select * from a inner join b on a.id = b.id where....
Someone can tell me how to do it?
Thanks in advance
The overall approach is not very nice, but in terms of getting what you want, this should do it.
fields = "*";
from = "TableA AS a INNER JOIN TableB AS B ON a.id = b.id";
whereStr = "a.id > 10";
orderBy = "a.id, b.id";
Set your input parameters to that, or just paste it in before the code you gave us and it will produce the command SELECT * FROM TableA AS a INNER JOIN TableB AS B ON a.id = b.id WHERE a.id > 10 ORDER BY a.id, b.id
Please note that orderBy = "a.id; DROP TABLE TableA;"; is a scary prospect

C# SQL Query Producing Different Results than Management Studio

SELECT
wl.WatchListId, wl.Code, wl.[Description], wl.DateCreated,
wl.CreatedBy, wl.DateModified, wl.ModifiedBy,
wpi.ParameterExpression as IndividualExpression,
wpb.ParameterExpression as BusinessExpression,
wpd.ParameterExpression as DefaultExpression,
CASE
WHEN EXISTS(SELECT 1 FROM SourceWatchList
WHERE SourceId = #SourceId AND WatchListId = wl.WatchListId)
THEN 1 ELSE 0
END AS IsActive
FROM
[WatchList] wl
LEFT JOIN
SourceWatchList swl ON wl.WatchListId = swl.WatchListId AND swl.SourceId = #SourceId
LEFT JOIN
(SELECT
ParameterExpression, SourceId, WatchListId
FROM WatchListParameter
WHERE EntityType = 'INDIVIDUAL') wpi ON wpi.SourceId = #SourceId
AND wpi.WatchListId = wl.WatchListId
LEFT JOIN
(SELECT
ParameterExpression, SourceId, WatchListId
FROM WatchListParameter
WHERE EntityType = 'BUSINESS') wpb ON wpb.SourceId = #SourceId
AND wpb.WatchListId = wl.WatchListId
LEFT JOIN
(SELECT ParameterExpression, SourceId, WatchListId
FROM WatchListParameter
WHERE EntityType = 'DEFAULT') wpd ON wpd.SourceId = #SourceId
AND wpd.WatchListId = wl.WatchListId
WHERE
wl.IsActive = 1
I have the above query. Pretty simple.
Here's a snippet from SQL Server Management Studio table :
and from the debugger in Visual Studio :
The Visual Studio table has no data in the 3 Expression Columns while the Management Studio (correctly) does. Can any tell me why that is, and what steps I can take to resolve the issue?
I'm 100% sure I've used the same parameter between the two as well.
string sql = #"SELECT wl.WatchListId,wl.Code,wl.[Description],wl.DateCreated,
wl.CreatedBy,wl.DateModified,wl.ModifiedBy,
wpi.ParameterExpression as IndividualExpression,
wpb.ParameterExpression as BusinessExpression,
wpd.ParameterExpression as DefaultExpression,
CASE WHEN EXISTS(Select 1 FROM SourceWatchList
WHERE SourceId = #SourceId AND WatchListId = wl.WatchListId)
THEN 1 ELSE 0 END AS IsActive
FROM [WatchList] wl
LEFT JOIN SourceWatchList swl on wl.WatchListId = swl.WatchListId and swl.SourceId = #SourceId
LEFT JOIN (Select ParameterExpression, SourceId, WatchListId FROM WatchListParameter WHERE EntityType = 'INDIVIDUAL') wpi
ON wpi.SourceId = #SourceId AND wpi.WatchListId = wl.WatchListId
LEFT JOIN (Select ParameterExpression, SourceId, WatchListId FROM WatchListParameter WHERE EntityType = 'BUSINESS') wpb
ON wpb.SourceId = #SourceId AND wpb.WatchListId = wl.WatchListId
LEFT JOIN (Select ParameterExpression, SourceId, WatchListId FROM WatchListParameter WHERE EntityType = 'DEFAULT') wpd
ON wpd.SourceId = #SourceId AND wpd.WatchListId = wl.WatchListId
where wl.IsActive = 1";
SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["WatchListCompliance"].ConnectionString);
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("#SourceId", SourceId);
DataTable dt = new DataTable();
using (SqlDataAdapter a = new SqlDataAdapter(cmd))
{
a.Fill(dt);
}
This might be a problem with types and equality. You can try using SqlDataType when you define the parameters on the sqlcommand. When you use addwithvalue without declaring a type it could be selecting the wrong type. Then you should use the type you declared in the sql expression.
cmd.Parameters.Add("#SourceId", SqlDbType.VarChar, 20);
cmd.Parameters["#SourceId"].Value = SourceId;
Wild guess: are you sure your session is configured the same way? Especially the SET ANSI_NULLS option, which changes how comparison behaves with regard to null values.
It is worth noting that some databases may have unusual default values, but some clients (e.g. ADO.NET) explicitely define their own values for the session when they connect, even if you don't ask them to.

Categories

Resources