Returning cross join instead of inner join - c#

I have two result sets from database into object and when I inner join them, it returns cross join. Following is my code:
var nw = new NorthwindEntities();
var employee1 = (from emp in nw.Employees
join ord in nw.Orders on emp.EmployeeID equals ord.EmployeeID
where emp.EmployeeID == 5
select new
{
empID = emp.EmployeeID,
empName = emp.FirstName,
ordDate = ord.OrderDate
}).ToList();
var employee2 = (from emp in nw.Employees
join ord in nw.Orders on emp.EmployeeID equals ord.EmployeeID
where emp.EmployeeID == 5
select new
{
empID = emp.EmployeeID,
empName = emp.FirstName,
shpAddress = ord.ShipAddress
}).ToList();
var employee = from e1 in employee1
join e2 in employee2 on new { e1.empID } equals new { e2.empID }
select new
{
empID = e1.empID,
empName = e1.empName,
ordDate = e1.ordDate,
orAdd = e2.shpAddress
};
gvAll.DataSource = employee.ToList();
Now when I join employee1 and employee2 into employee, I get a cross join of those data set. Any help would be highly appreciated.
My main target behind this is to have data returned from database stored in some place temporarily so I can work it with later with other data retrieved from database.
employee1 and employee2 uses same query for employee id (5) except employee1 has empID, empName and OrderDate where as employee2 has empID, empName and shipAddress. Now I want empID, empName, OrderDate and ShipAddress out of employee1 and employee2 in employee. empID is common in both but I am getting a cross join. Thank you.

In employee1 and employee2 you will aslo need the OrderId column to and then join them by both cos you need to get an equal unique key on both tables.
and from what you wrote I think that empID is not unique in either tables cos you can have more orders for same empID
So first you need a unique key on both employee1 and employee2 then you can join on that.

The result returned from function is logically correct, it is not a cross join. empID has some duplicate row in some table so, data is looking like a cross join.
Use distinct then it will return your desired output.

Related

SQL query to select everything from 1 table and 1 column(same name as in table 1) from another table

I have 3 tables.
table1 :
Products:
ProductId Category Model Price Quantity
table2:
OrderLines:
OrderId ProductId Quantity
table3:
Orders:
OrderId CustomerId
(theres also a customer table but it doesnt matter)
Now I want to select all the products data from Products table that have ProductId = ProductId in OrderLines table, but get the quantity data (of those same products) from the OrderLines table.
Tried all kinds of queries, couldn't find one that works.
heres the last thing i kind of tried:
SELECT tb1.* ,tb2.[Quantity]
FROM [Products] tb1, [OrderLines] tb2
WHERE tb1.[ProductId] IN (
SELECT [ProductId] FROM [OrderLines] WHERE OrderId = #orderId)
INNER JOIN [OrderLines] tb2 ON[Products].Quantity = [OrderLines].Quantity";
didn't worked.
any suggestions?
Thanks a lot.
sample data:
Orders:
OrderId CustomerId
1 2
OrderLines:
OrderId ProductId Quantity
1 3 1
1 4 5
Products:
ProductId Category Model Price Quantity
3 "wow" "hd" 30 5
4 "yay" "sd" 50 60
5 "wow" "ss" 12 5
expected output:
array of products:
each object is type Product, having the same fields in as in the table. (already defined it's class).
first object in the array is:
productId = 3, Category="wow",Model="hd", price=30,Quantity =
1 (**1! not 5)
2nd object:
productId = 4, Category="yay",Model="sd",price=50,Quantity=5
I am using c# in visual studio, Winforms.
database is Access.
this is the function:
public Product[] GetProductsByOrderId(int orderId)
{
DataSet ds = new DataSet();
ArrayList arrProducts = new ArrayList();
//"SELECT tb1.* ,tb2.[Quantity] FROM [Products] tb1, [OrderLines] tb2 WHERE tb1.[ProductId] IN (SELECT [ProductId] FROM [OrderLines] WHERE OrderId = #orderId) INNER JOIN [OrderLines] tb2 ON[Products].Quantity = [OrderLines].Quantity"
string cmdStr = "SELECT p.*, ol.Quantity as OrderLineQuantity from Products as p inner join OrderLines as ol on p.Id = ol.ProductId";
using (OleDbCommand command = new OleDbCommand(cmdStr))
{
command.Parameters.AddWithValue("#orderId", orderId);
ds = GetMultipleQuery(command);
}
DataTable dt = new DataTable();
try
{
dt = ds.Tables[0];
}
catch { }
foreach (DataRow tType in dt.Rows)
{
Product productData = new Product();
productData.ProductId = int.Parse(tType[0].ToString());
productData.Category = tType[1].ToString();
productData.Model = tType[2].ToString();
productData.Price = double.Parse(tType[3].ToString());
productData.Quantity = int.Parse(tType[4].ToString());
arrProducts.Add(productData);
}
return (Product[])arrProducts.ToArray(typeof(Product));
}
Sorry and I Hope it's more clear now.
This will get you four columns from product and 1 from orderlines based on a join.
SELECT p.productId, p.category, p.model, p.price, o.quantity
from products p
join orderlines o on p.productid = o.productid
Small style note -- don't use the plural for the table name. eg use
product not products and orderline not orderlines. No good reason except that is how everyone does it.
SELECT p.*, ol.Quantity as OrderLineQuantity from
Products as p
inner join
OrderLines as ol
on p.Id = ol.ProductId
The actual query that works is:
SELECT p.ProductId, p.Category, p.Model, p.Price, o.Quantity
FROM [Products] p
INNER JOIN [OrderLines] o ON p.ProductId = o.ProductId
WHERE o.OrderId = #orderId
ORDER BY p.ProductId
Thanks for #Hogan for getting me started in the right direction.
edited thanks to lucas mention, deleted the WHERE IN SELECT...
select p.ProductId,sum(ol.Quantity)
from Products p
inner join orderlines ol on p.ProductID=ol.ProductID
group by p.ProductId

Subquery in using LINQ to SQL

I have two tables.
1) Employee which have Id, Name, DeptId columns.
2) Department which have Id and DeptName columns.
I want to find all department which have no any employee using Linq to sql.
IN sql I use below query:
Select * from Department Where Id not in
(Select DeptId from Employee where DeptId Is not Null )
You can do this using LINQ left join like this:-
var result = from d in departments
join e in employees
on d.Id equals e.DeptId into es
from x in es.DefaultIfEmpty()
where x == null
select new Department { Id = d.Id, Name = d.Name};
Check this Fiddle for example with some custom objects.
In SQL this is equivalent to:-
SELECT D.*
FROM Department D
LEFT JOIN Employee E
ON D.Id = E.DeptId
WHERE E.id IS NULL
I hope this will work for you.
var empWithDepartments = from emp in Employee where emp.DeptId != NULL select emp.DeptId;
var result = from dep in Department where !empWithDepartments.Contains(dep.Id) select dep;
Try this:
var query = from d in Departments
where !(from e in Employees select e.FkDepartmentId).Contains(d.DepartmentId)
select d;
According to this post this would work with LINQ-TO-SQL but not with LINQ-TO-EF.

EF Core left join with count

i have got 3 tables on MySql database. i want to do left join between this 3 tables and count with group by.
City Table
Id
Name
School Table
Id
CityId
Name
Student Table
Id
SchoolId
Name
/* MySql raw query like this: */
select Count(tstudent.id) as StudentCount, tcity.Id, tcity.Name
from City tcity
left join School tschool on tcity.Id = tschool.CityId
left join Student tstudent on tschool.Id = tstudent.SchoolId
group by tcity.Id;
With EF Core i try like this:
class CityWithStudentCount {
public int Id { get;set; }
public string CityName { get;set; }
public int StudentCount { get;set; }
}
Ef Core :
var db = new MyDbContext();
var result = (from city in db.City
join school in db.School on city.Id equals school.CityId into tcity
from r1 in tcity.DefaultIfEmpty()
join student in db.Student on school.Id equals student.SchoolId into tschool
from r2 in tschool.DefaultIfEmpty()
select new CityWithStudentCount
{
Id = city.Id,
CityName = city.Name,
StudentCount = tschool.count()
} into s1
group s1 by s1.Id)
.Select(s=>s.ToList())
.ToList();
Result must be like that :
1 City1 10
2 City2 3
3 City3 0
4 City4 0
5 City5 12
How can i do like this query for this result with Entity Framework Core. Thank you.
Your query is wrong.
var result = (from city in db.City
join school in db.School on city.Id equals school.CityId into t1
from school in t1.DefaultIfEmpty()
join student in db.Student on school.Id equals student.SchoolId into t2
from student in t2.DefaultIfEmpty()
group student by new { city.Id,city.Name } into cityGrouped
select new CityWithStudentCount
{
Id = cityGrouped.Key.Id,
CityName = cityGrouped.Key.Name,
StudentCount = cityGrouped.Count(x => x.student != null)
}
.ToList();
Also, I strongly suggest you to use navigation properties instead of manual building joins.

How to join two tables with one table having distinct value in LINQ sql?

I have two tables emp_details where i have emp_id, emp_name and emp_addresss as columns and another table emp_hierarcy where i have emp_id, emp_mgid with multiple rows with same emp_id.
I want to write a linq query i.e, to join two table upon emp_id with distinct emp_id in emp_hierarcy. I know how to join tables in sqlserver and i have return this query in sqlserver
SELECT
DISTINCT
eh.emp_id
FROM
emp_details ed
LEFT OUTER JOIN emp_hierarcy eh ON ed.emp_id = eh.emp_id
i'm able to print only emp_id how to get all the details in LINQ query ?
Select all fields that you are interested in:
var items = (from a in emp_details
join b in emp_hierarcy on a.emp_id equals b.emp_id
select new
{
emp_id = a.emp_id,
emp_name = a.emp_name,
emp_address = a.emp_address,
emp_mgid = b.emp_mgid
}).Distinct();
foreach(var item in items)
{
Console.WriteLine(item.emp_address);
...
}
(from a in emp_details
join b in emp_hierarcy on a.emp_id equals b.emp_id
select new
{
emp_id = a.emp_id
}).Distinct();
Alternatively you can try,
(from a in emp_details
join b in emp_hierarcy on a.emp_id equals b.emp_id
select new
{
emp_id = a.emp_id
}).DistinctBy(c => c.emp_id)

LINQ concatenate values from associated tables

Let'say there's a basic SQL db with the following structure:
Customers table
Customer ID
Name
PostCode
Email
Orders table
Order ID
Customer ID
Description
Items table
Item ID
Order ID
Name
Cost
So a customer can have many orders and an order can have many items.
What's the most appropriate LINQ query to run in order to achieve the following result where the Order Item Names result is a comma separated string:
Customer Name | Customer Email | Order Item Names
So effectively the Orders table is acting like a link table between the Customer and Order Items tables. I then want to concatenate the names of all items which are associated with all orders into a single string and return it in the same result as the customer details.
I've got the following working as expected which will return a result for each order item:
IQueryable<CustomerSearchResult> customerSearchResult = from customer in db.Customers
join order in db.Orders on customers.CustomerId equals order.CustomerId
join item in db.OrderItems on order.OrderId equals item.OrderId
where customerId.Equals(userId)
select new CustomerSearchResult {
customerName = customer.Name,
customerEmail = customer.Email,
itemName = item.Name
};
EDIT 21st March 2014
There are some cases when there will be no associated OrderItems in which case the CustomerSearchResult should still be returned but with the ItemNames property empty.
After you have results
var query = from c in db.Customers
join o in db.Orders on c.CustomerId equals o.CustomerId
join i in db.OrderItems on o.OrderId equals i.OrderId
where c.CustomerId == userId
select new {
CustomerName = c.Name,
CustomerEmail = c.Email,
ItemName = i.Name
};
Group them and concatenate item names:
var result = from r in query.AsEnumerable()
group r by new { r.CustomerName, r.CustomerEmail } into g
select new CustomerSearchResult {
CustomerName = g.Key.CustomerName,
CustomerEmail = g.Key.CustomerEmail,
ItemNames = String.Join(",", g.Select(r => r.ItemName))
};
You should do names concatenation in-memory, because EF will not be able to translate it into SQL.

Categories