SQL Select multiple column values - mysql

I'm having difficulty with some SQL - and finding it hard to describe so please bear with me. I'm trying to select products that have an x number of correct features. To simplify things, the problem I'm having is with a few tables. The relevant information about my tables, is:
products(**product_id**)
features(**feature_id, product_id**, value_id)
featurenames(**feature_id**, name)
featurevalues(**value_id**, value)
I am trying to select all products that, for example, are for sex:male age:children, with age and sex being names in the featurenames table and male and children being values in the featurevalues table. This is part of another bigger query that gets all the products by category, which I haven't included as it will just complicate things. Thank you for your help in advance.

It's the table so nice, you join to it twice.
Select
P.Product_ID
From
Products P
Inner Join Features F1 On P.Product_ID = F1.Product_ID
Inner Join FeatureNames FN1 On F1.Feature_ID = FN1.Feature_ID And FN1.Name = 'sex'
Inner Join FeatureValues FV1 On F1.Value_ID = FV1.Value_ID And FV1.Value = 'male'
Inner Join Features F2 On P.Product_ID = F2.Product_ID
Inner Join FeatureNames FN2 On F2.Feature_ID = FN2.Feature_ID And FN1.Name = 'age'
Inner Join FeatureValues FV2 On F2.Value_ID = FV2.Value_ID And FV1.Value = 'children'

Related

quantity and ext price being multiplied by three?

I am building a table in reporting services and am not getting the results I expect. It appears that my table is taking my data and multiplying by 3. In the example below the quantity should be 1 and the ext price should be roughly $322. I have spot checked a few of these orders in our system and it appears it is doing this across the board. Below is the query I built but I am not sure what is causing the issue. Any suggestions? Thanks!
SELECT
OrderDetail.Quantity
,OrderDetail.PartNo
,OrderDetail.UnitPrice
,Orders.OrderNumber
,Orders.ReqDate
,Orders.ShpAddr_City
,Orders.ShpAddr_State
,act.PartMapping.SalesRevenue
,MasterPartList.ProductCategoryID
,Categories.Description
,OrderDetail.LocationID
,Orders.InvAddrCompanyName
,Orders.Status
,CustomerUserDefValues.UserDefValue
,UserDefs.UserDefID
,Orders.ClosedDate
FROM
OrderDetail
INNER JOIN Orders
ON OrderDetail.oKey = Orders.oKey
INNER JOIN act.PartMapping
ON OrderDetail.PartNo = act.PartMapping.PartNo
INNER JOIN MasterPartList
ON OrderDetail.PartNo = MasterPartList.MasterPartNo
INNER JOIN Categories
ON MasterPartList.ProductCategoryID = Categories.ID
INNER JOIN CustomerUserDefValues
ON Orders.CustomerID = CustomerUserDefValues.CustomerID AND Orders.SiteID =
CustomerUserDefValues.SiteID
INNER JOIN UserDefs
ON CustomerUserDefValues.UserDefID = UserDefs.UserDefID
WHERE dbo.UserDefs.[UserDefID] in (#UserDefID) and act.PartMapping.[SalesRevenue] in
(#ValueAddAccount)

Querying Many to Many When 3 Tables Connected to A junction

DB MODEL
I have Model Which is Connected in above Order Now I want to Select Style Names From Style Table.
Case 1 : I want the Style Names which are both intersecting Category and Gender
Case 2 : I want the Style Names which are intersecting Gender only regardless of category.
I am newbie to SQL is there any efficient way to Get the desired result using SQL JOINS . Any Help in such case will be appreciated or is there any modelling solutions to deal with such type of situations.
Here is how you would join your tables:
SELECT *
FROM `style`
INNER JOIN `StyleCategoryGender` ON `StyleCategoryGender`.`SID` = `style`.`Code`
INNER JOIN `StyleCategoryGender` ON `Category`.`Code` = `StyleCategoryGender`.`GID`
INNER JOIN `StyleCategoryGender` ON `Gender`.`Code` = `StyleCategoryGender`.`CID`
then you can add WHERE clauses as needed
SELECT *
FROM `style`
INNER JOIN `StyleCategoryGender` ON `StyleCategoryGender`.`SID` = `style`.`CODE`
INNER JOIN `StyleCategoryGender` ON `Category`.`Code` = `StyleCategoryGender`.`GID`
INNER JOIN `StyleCategoryGender` ON `Gender`.`Code` = `StyleCategoryGender`.`CID`
WHERE `Gender`.`Name` = 'Female'

use multiple results of a query within the query with joins

I have some tables in my database, three main ones and one that holds the many-to-many relations.
1. Student (student_id, student_name)
2. Sport (sport_id, sport_name)
3. Departm (depart_id, depart_name)
4. Sch (sch_id, sch_name)
5. StudSport(relationid, studendid, sportid, departid, schid)
What I want to do is e.g. retrieve the name of the department based on the relations when I know the id. I can get the ids like this:
SELECT departid, schid from studsport
inner join Student on student_id = studentid
inner join Sport on sport_id = sportid
where student_id = 1 and sport_id=2
but I want to get the names of the department and the Sch from their corresponding tables, and I dont know how to do that.
As you don't select anything from Student or Sport, you can remove the corresponding inner joins.
SELECT d.depart_name, sch.sch_name FROM StudSport s
INNER JOIN Sch sch ON s.schid = sch.sch_id
INNER JOIN Departm d ON s.departid = d.depart_id
WHERE s.studendid = 1 AND s.sportid = 2
Something like this???
select sch.sch_nam, departm.depart_name,
-- what you have already --
Left outer Join StudSport on Student.student_id = Studsport.studentid and Sport.sport_id = StudSport.sportid
left outer Join Sch on StudSport.schid = Sch.sch_id
left outer join Departm on studsport.depart_id = studsport.departid
This is untested, a fiddle makes it much easier to give answers because of that.
EDIT - I misread your original query - before the downvotes start to rain - fixing it right now.
The way you should use LEFT OUTER and INNER joins is how the data is meant (again, a fiddle will normally be usefull) but it's just a couple of joins from what you have i guess:
select *
from studsport
join student on studsport.studentid = student.student_id
join sport on studsport.sportid = sport.sport_id
left outer Join Sch on StudSport.schid = Sch.sch_id
left outer join Departm on studsport.depart_id = studsport.departid
where student_id = 1 and sport_id=2

Full outer join in mysql with movie database

Hi I have the following tables and columns.
movie: ID, title
person: ID, name
involved: personID, movieID
I need to answer the question:
"Which movies have either John Travolta or Uma Thurman, but not both starred in?"
I couldn't figure out how to do this without creating new tables, so I made 2 new tables. And tried to do the full outer join on, where you dont get intersecting results. I found out that you can't do full outer joins in mysql but had to do a left join, unioned with a right join. I tried this but don't get the results I wanted at all. I have been stuck for a while now. Can anyone point me in the right direction?
This is what I have so far.
DROP TABLE IF EXISTS Umatable;
DROP TABLE IF EXISTS Johntable;
CREATE TABLE Umatable(title VARCHAR(500));
CREATE TABLE Johntable(title VARCHAR(500));
INSERT INTO Umatable
SELECT m.title
FROM movie m, person p, involved i
WHERE p.name = "Uma Thurman"
AND p.id = i.personid
AND m.id = i.movieiD;
INSERT INTO Johntable
SELECT m.title
FROM movie m, person p, involved i
WHERE p.name = "John Travolta"
AND p.id = i.personid
AND m.id = i.movieiD;
SELECT *
FROM Umatable
LEFT JOIN Johntable ON Umatable.title = Johntable.title
WHERE Johntable.title IS NULL OR Umatable.title IS NULL
UNION
SELECT *
FROM Umatable
RIGHT JOIN Johntable ON Umatable.title = Johntable.title
WHERE Johntable.title IS NULL OR Umatable.title IS NULL
I would do this using aggregation and having:
select i.movieId
from involved i join
person p
on p.id = i.personId
group by i.movieId
having sum(p.name in ('John Travolta', 'Uma Thurman')) = 1;
A count(*) inside a correlated subquery will work:
select *
from movie m
where 1 = (select count(*)
from involved i
join person p
on p.ID = i.personID
and p.name IN ('John Travolta', 'Uma Thurman')
where i.movieID = m.ID)
SQLFiddle Demo

SQL: Get latest entries from history table

I have 3 tables
person (id, name)
area (id, number)
history (id, person_id, area_id, type, datetime)
In this tables I store the info which person had which area at a specific time. It is like a salesman travels in an area for a while and then he gets another area. He can also have multiple areas at a time.
history type = 'I' for CheckIn or 'O' for Checkout.
Example:
id person_id area_id type datetime
1 2 5 'O' '2011-12-01'
2 2 5 'I' '2011-12-31'
A person started traveling in area 5 at 2011-12-01 and gave it back on 2011-12-31.
Now I want to have a list of all the areas all persons have right now.
person1.name, area1.number, area2.number, area6.name
person2.name, area5.number, area9.number
....
The output could be like this too (it doesn't matter):
person1.name, area1.number
person1.name, area2.number
person1.name, area6.number
person2.name, area5.number
....
How can I do that?
This question is, indeed, quite tricky. You need a list of the entries in history where, for a given user and area, there is an 'O' record with no subsequent 'I' record. Working with just the history table, that translates to:
SELECT ho.person_id, ho.area_id, ho.type, MAX(ho.datetime)
FROM History AS ho
WHERE ho.type = 'O'
AND NOT EXISTS(SELECT *
FROM History AS hi
WHERE hi.person_id = ho.person_id
AND hi.area_id = ho.area_id
AND hi.type = 'I'
AND hi.datetime > ho.datetime
)
GROUP BY ho.person_id, ho.area_id, ho.type;
Then, since you're really only after the person's name and the area's number (though why the area number can't be the same as its ID I am not sure), you need to adapt slightly, joining with the extra two tables:
SELECT p.name, a.number
FROM History AS ho
JOIN Person AS p ON ho.person_id = p.id
JOIN Area AS a ON ho.area_id = a.id
WHERE ho.type = 'O'
AND NOT EXISTS(SELECT *
FROM History AS hi
WHERE hi.person_id = ho.person_id
AND hi.area_id = ho.area_id
AND hi.type = 'I'
AND hi.datetime > ho.datetime
);
The NOT EXISTS clause is a correlated sub-query; that tends to be inefficient. You might be able to recast it as a LEFT OUTER JOIN with appropriate join and filter conditions:
SELECT p.name, a.number
FROM History AS ho
JOIN Person AS p ON ho.person_id = p.id
JOIN Area AS a ON ho.area_id = a.id
LEFT OUTER JOIN History AS hi
ON hi.person_id = ho.person_id
AND hi.area_id = ho.area_id
AND hi.type = 'I'
AND hi.datetime > ho.datetime
WHERE ho.type = 'O'
AND hi.person_id IS NULL;
All SQL unverified.
You're looking for results where each row may have a different number of columns? I think you may want to look into GROUP_CONCAT()
SELECT p.`id`, GROUP_CONCAT(a.`number`, ',') AS `areas` FROM `person` a LEFT JOIN `history` h ON h.`person_id` = p.`id` LEFT JOIN `area` a ON a.`id` = h.`area_id`
I haven't tested this query, but I have used group concat in similar ways before. Naturally, you will want to tailor this to fit your needs. Of course, group concat will return a string so it will require post processing to use the data.
EDIT I thikn your question has been edited since I began responding. My query does not really fit your request anymore...
Try this:
select *
from person p
inner join history h on h.person_id = p.id
left outer join history h2 on h2.person_id = p.id and h2.area_id = h.area_id and h2.type = 'O'
inner join areas on a.id = h.area_id
where h2.person_id is null and h.type = 'I'