I have such database structure (1 - one, 0 - many)
Product 1->0 Orders 0->1 Users
I need to find all users for specified product, I have started writing linq query but don't know how to finish it.
public IQueryable<User> GetUsers(int productId)
{
return _db.Products.First(p => p.Id == productId)....
}
First things first, the First method will only return the first item that meets your criteria, and since you want to return an IQueryable of Users, this is probably not what you want.
Second, I think the easiest way to get started with Linq-to-SQL is to use query notation, especially when you're dealing with joins, which don't look too pretty when using lambda expressions.
public IQueryable<User> GetUsers(int productId)
{
return from p in _db.Products
join o in _db.Orders on p.Id equals o.productId
join u in _db.Users on o.userId equals u.userId
where p.productId == productId
select u;
}
Something like this should work (written in VB.net):
Dim users() = (from x in _db.Users
Join y in _db.Orders on y.userid equals x.userid
Join z in _db.Product on z.productid equals y.productid
where z.productname = "ProductName"
select x.firstname,x.lastname,x.email,e.tel).toarray()
I've guessed at the fields in the tables, but this will give you the firstname, lastname email and telephone number of users that have ordered a certain product.
Thanks
Paul.
Related
I was given the following question for an assignment
Write a SQL statement to show the sum of Hours Worked for each Type of OWNER but exclude services of employees who have Experience Level of Junior and exclude any Owner Type with Less Than Four members
I'm having a hard time figuring out how to accomplish the last part of the question. I believe that it would require counting a portion of a select statement but I'm not sure how to do that.
So far, this is what I have:
SELECT SUM(HoursWorked), OwnerType
FROM PROPERTY_SERVICE
JOIN EMPLOYEE ON EMPLOYEE.EmployeeID=PROPERTY_SERVICE.EmployeeID
JOIN OWNED_PROPERTY ON OWNED_PROPERTY.PropertyID = PROPERTY_SERVICE.PropertyID
INNER JOIN OWNER ON OWNER.OwnerID=OWNED_PROPERTY.OwnerID
WHERE NOT EMPLOYEE.ExperienceLevel='Junior'
*This is where I believe the solution should go*
GROUP BY OWNER.OwnerType;
Presumably, you just want a HAVING clause:
SELECT SUM(HoursWorked), o.OwnerType
FROM PROPERTY_SERVICE ps
JOIN EMPLOYEE e ON e.EmployeeID = ps.EmployeeID
JOIN OWNED_PROPERTY op ON op.PropertyID = ps.PropertyID
INNER JOIN OWNER o ON o.OwnerID = op.OwnerID
WHERE e.ExperienceLevel <> 'Junior'
GROUP BY o.OwnerType
HAVING COUNT(*) < 4
This excludes groups of rows having the same OwnerType that contain less than 4 rows. You might need to adjust the expression to your exact definition of a member.
Note that I added table aliases to the query to make it easier to read and write. I would also recommend prefixing column HoursWorked with the table it belongs to, to avoid ambiguity.
Is there a way to do a conditional JOIN so that it returns columns of either of one of the child tables based on a parent table field?
tl;dr:
I am trying to implement Class Table Inheritance (aka Table Per Type Inheritance) in mySQL. AFAIK it's not offered out of the box so some hacking around is needed to make it tick.
Considering the following SQL schema.
What I'd like to do:
Get records of CustomerIndividual IF they exist OR CustomerOrganization IF they exist.
I'm passing around idCustomer for my WHERE clauses.
An Ideal Result Set:
If Customer.typeIndividual = TRUE:
If Customer.typeOrganization = TRUE:
It's important to note that this query will always return 1 record only, so yes the column number would be variable.
What I'm currently doing:
SELECT *
FROM Customer
LEFT JOIN CustomerIndividual
ON Customer.idCustomer = CustomerIndividual.idCustomer
LEFT JOIN CustomerOrganization
ON Customer.idCustomer = CustomerOrganization.idCustomer
WHERE Customer.idCustomer = ?
but this of course:
returns ALL columns for Customer, CustomerIndividual & CustomerOrganization
returns even duplicate columns, e.g idCustomer which appears on all 3 tables.
produces columns of CustomerOrganization even if the Customer is an Individual and vice-versa.
My question:
Is there a way to do a conditional JOIN so that it returns columns of either of one of the child tables based on the Customer.typeIndividual/Customer.typeOrganization fields?
Notes:
Either Customer.typeIndividual OR Customer.typeOrganization can be TRUE at any given time. Not both at the same time. The Customer can be either an Individual OR an Organization.
I'm open to restructuring if it makes things more simple. I'm having the feeling that the Customer.typeIndividual OR Customer.typeOrganization differentiation flag I use is somehow redundant, i.e perhaps I could infer whether a Customer is an Individual/Organization by looking which of the child-tables is full.
I'm aware I could make completely different queries on the application-level but yes, I'm looking for a silver-bullet.
Maybe you can do this, but I dont recommend it.
SELECT
Customer.*,
COALESCE(CI.firstName, CO.organizationName) AS firstName_or_organizationName,
COALESCE(CI.maidenName, CO.registrationNo) AS maidenNamee_or_registrationNo,
lastName -- here you get last_name or NULL if is an organization
FROM Customer C
LEFT JOIN CustomerIndividual CI
ON Customer.idCustomer = CustomerIndividual.idCustomer
LEFT JOIN CustomerOrganization CO
ON Customer.idCustomer = CustomerOrganization.idCustomer
WHERE Customer.idCustomer = ?
Or use a store procedure
DELIMITER ;;
CREATE DEFINER=CURRENT_USER PROCEDURE stored_procedure_name(IN CustomerID INT)
BEGIN
DECLARE boolTypeIndividual INT;
SELECT Customer.typeIndividual into boolTypeIndividual
FROM Customer
WHERE Customer.idCustomer = CustomerID
IF (boolTypeIndividual) THEN
SELECT C.*, CI.*
FROM Customer C
LEFT JOIN CustomerIndividual CI
ON Customer.idCustomer = CustomerIndividual.idCustomer
WHERE Customer.idCustomer = CustomerID
ELSE
SELECT C.*, CO.*
FROM Customer C
LEFT JOIN CustomerOrganization CO
ON Customer.idCustomer = CustomerOrganization.idCustomer
WHERE Customer.idCustomer = CustomerID
END IF
END;;
DELIMITER ;
well, I want to get the best selling product, but when I want to get them. it just return the best selling product, but not idventa,idproduct,and description. well return the values but they are wrong values which they belong to other one. I need someone help me to correct me statement on sql because I want to return the right values like: idventa: 7 - idproducto: 10 , descripcion: IPHONE 4S, best_selling_product: 5000, and not the other values which they are not belong to the sentence
SELECT
idventa,idproducto,descripcion,MAX(venta_detalle.cantidad) AS best_selling_product
FROM venta_detalle
INNER JOIN producto
ON venta_detalle.idproducto = producto.id
Without knowing your table structures, it's a little difficult to guess what you're looking for. Sometimes you can get away with adding a group by clause assuming distinct values exist for that field.
Other times you need to join the table back to itself using aggregation in a subquery:
select
p.idproducto,
p.descripcion,
vd.idventa,
vd.cantidad
from producto p
join venta_detalle vd on vd.idproducto = p.id
join (select idproducto, max(cantidad) best_selling_product
from venta_detalle
group by idproducto) vd2 on vd.idproducto = vd2.idproducto and
vd.cantidad = vd2.best_selling_product
Although max() will return the highest number and without a group by it will also collapse the resultset into a single record, however, there is no guarantee that the other fields will come from the same record as the max. I suggest a simple order by and limit combo to get the record with the highest value:
SELECT
idventa,idproducto,descripcion, venta_detalle.cantidad AS best_selling_product
FROM venta_detalle
INNER JOIN producto
ON venta_detalle.idproducto = producto.id
ORDER BY venta_detalle.cantidad DESC
LIMIT 1
I have this MYSQL query:
SELECT *
FROM store_product
LEFT JOIN store_promo_product ON store_product.store_product_id = store_promo_product.store_product_id
LEFT JOIN store_promo ON store_promo.store_promo_id = store_promo_product.store_promo_id
JOIN product ON product.product_id = store_product.product_id
WHERE store_product.store_id = 338 and store_promo_product.store_product_id=52
While i know how to convert it to codeigniter Active Record using Join syntax, the problem is that sometimes i can have few "store_product_id" from the same store so the query will return the product details + promo details twice or more (depends how much promos i have for the same product). I am looking for away to return only ONE product (because it is the same product) with two promos (because they are different promo sales) ..
Hope i explained my self.
even pure mysql will do if possible of course.
I ended up splitting the function into two functions which seemed to work.
I am trying to write a complex query with query builder and I need help(I am a complete noob in join queries) The situation is like this, I have a country table, a hotel table with country_id relationship, and promotions with hotel_id relationship.
So hotels have countries, and promotions have hotels. Now I need to find all promotions who belong to a a set of countries. To do that I need to check that the hotels they belong to are in those countries.
Anyway can someone help me build the query with query builder? I'll accept mysql queries as well.
Assuming you have set up your relationships with #OneToMany and #ManyToOne in your entities and you've populated a desired Doctrine collection or array of IDs of countries into $countries:
$result = $this->getDoctrine()->getManager()->createQueryBuilder()
->select('c, h, p')
->from('AcmeBundle:Promotion', 'p')
->innerJoin('p.hotels', 'h')
->innerJoin('h.country', 'c')
->where('c IN (:countries)')
->setParameter('countries', $countries)
->getQuery()
->getResult();
The resulting SQL will end up being something similar to:
SELECT c.*, h.*, p.* FROM promotions p
INNER JOIN hotels h ON p.hotel_id = h.id
INNER JOIN country c ON h.country_id = c.id
WHERE c.id IN (?)
Note that this query will not work without defining your Doctrine entities appropriately. Since you didn't provide your Entity configuration, I had to answer your question with assumptions. Here's some more information on setting up your Database with Doctrine, specifically Entity Relationship mapping