Fetching MySQL data going through multiple tables - mysql

I'm wanting to do the following:
Select everything from product that matches the value of type_id from both tables product and system_type. Then with those matched results, match cat_id from both tables system_type and system_cat and then refine the final result where cat_type = 0 from the system_cat table.
Current SQL seems to have a syntax error:
SELECT * FROM product
JOIN system_type
USING (type_id)
JOIN system_cat
USING (cat_id)
WHERE cat_type = 0
What else I've tried:
SELECT * FROM product
JOIN system_type
USING system_type.type_id = product.type_id
JOIN system_cat
USING system_type.cat_id = system_cat.cat_id
WHERE system_cat.cat_type = 0

Try this. You may need to explicitely type out the columns you need
SELECT * FROM product as pr
INNER JOIN system_type as st
ON st.type_id = pr_id
INNER JOIN system_cat as sc
ONH st.cat_id = sc.cat_id
WHERE sc.cat_type = 0

Syntax changes when using table_name.column method. Use ON and not USING.
SELECT * FROM product
JOIN system_type
ON system_type.type_id = product.type_id
JOIN system_cat
ON system_type.cat_id = system_cat.cat_id
WHERE system_cat.cat_type = 0

Related

MYSQL - CONCATENATE a lookup tables columns into one row

I have the following table structure:
tbl_catalogue_state
In tbl_catalogue there is a part number 58674 that has three states in the tbl_catalogue_state_lk table. Here is the result when I run a query inner joining the three tables.
As expected there are multiple rows returned.
Is there a way to only return one row having the values for each catalgue_state_id on the same row?
I would also like the ability to ignore a row for example:
select tbl_catalogue.catalogue_part, tbl_catalogue_state.catalogue_state_id from tbl_catalogue
inner join tbl_catalogue_state_lk on tbl_catalogue.catalogue_id = tbl_catalogue_state_lk.catalogue_id
inner join tbl_catalogue_state on tbl_catalogue_state_lk.catalogue_state_id = tbl_catalogue_state.catalogue_state_id
where tbl_catalogue_state_lk.catalogue_state_id <> 1;
The above select still returns two rows.
UPDATE
I was able to use GROUP_CONCAT:
select tbl_catalogue.catalogue_part, GROUP_CONCAT(tbl_catalogue_state.catalogue_state_id) as cat_state from tbl_catalogue
inner join tbl_catalogue_state_lk on tbl_catalogue.catalogue_id = tbl_catalogue_state_lk.catalogue_id
inner join tbl_catalogue_state on tbl_catalogue_state_lk.catalogue_state_id = tbl_catalogue_state.catalogue_state_id
where tbl_catalogue_state_lk.catalogue_state_id <> 1
group by tbl_catalogue.catalogue_id;
My issue is the above statement still returns a row. I need it to return nothing.
I was able to use not exists:
select tc.catalogue_part, GROUP_CONCAT(tcs.catalogue_state_id) as cat_state from tbl_catalogue as tc
inner join tbl_catalogue_state_lk as tcsl on tc.catalogue_id = tcsl.catalogue_id
inner join tbl_catalogue_state as tcs on tcsl.catalogue_state_id = tcs.catalogue_state_id
where
not exists
(
select tcsl2.catalogue_state_id from tbl_catalogue_state_lk as tcsl2
where tcsl2.catalogue_state_id = 6 and tcsl2.catalogue_id = tc.catalogue_id
)
and
not exists
(
select tcsl3.catalogue_state_id from tbl_catalogue_state_lk as tcsl3
where tcsl3.catalogue_state_id = 1 and tcsl3.catalogue_id = tc.catalogue_id
)
and
not exists
(
select tcsl3.catalogue_state_id from tbl_catalogue_state_lk as tcsl3
where tcsl3.catalogue_state_id = 2 and tcsl3.catalogue_id = tc.catalogue_id
)
group by tc.catalogue_id;

SQL Query based on multiple where conditions

I've got a script where checked in employee's can see the stock inventory from each other, linked with their personal stock location, so each checked in employee can see which items are in stock at different locations. However, I want the main stock (id of 1, which is not attached to an employee) to be showed always, but I can't get the query right because one of the where statements is clearly not correct:
`stock_locations`.`location_id` = 1 AND
`workschedule`.`checkedIn` = 1 AND
Rememeber, the main stock is not linked to an employee, so it doesn't show up at the workschedule table. If I remove the first statement, It clearly shows up all the checked in employee's with their location, but that doesn't give me the main stock. If I remove the second statement, it only shows me the main stock.
How can I solve this issue within SQL? This is btw the full statement:
SELECT
`item_quantities`.`item_id`,
`stock_locations`.`location_name`,
`item_quantities`.`quantity`,
`people`.`first_name`
FROM
`item_quantities`
JOIN `stock_locations` ON `item_quantities`.`location_id` = `stock_locations`.`location_id`
JOIN `items` ON `item_quantities`.`item_id` = `items`.`item_id`
LEFT JOIN `workschedule` ON `workschedule`.`linked_storage` = `stock_locations`.`location_id`
LEFT JOIN `people` ON `workschedule`.`employee_id` = `people`.`person_id`
WHERE
`stock_locations`.`location_id` = 1 AND
`workschedule`.`checkedIn` = 0 AND
`items`.`unit_price` != 0 AND
`items`.`deleted` = 0 AND
`stock_locations`.`deleted` = 0 NULL
Thanks in advance!
Make it an OR statement inside of parens.
(`stock_locations`.`location_id` = 1 OR `workschedule`.`checkedIn` = 1) AND
This will return all records that match either the main stock or the employee.
You need to use the OR operator. Clearly both things can't happen at the same time, so you need to specify each set of acceptable conditions.
SELECT
`item_quantities`.`item_id`,
`stock_locations`.`location_name`,
`item_quantities`.`quantity`,
`people`.`first_name`
FROM
`item_quantities`
JOIN `stock_locations`
ON `item_quantities`.`location_id` = `stock_locations`.`location_id`
JOIN `items`
ON `item_quantities`.`item_id` = `items`.`item_id`
LEFT JOIN `workschedule`
ON `workschedule`.`linked_storage` = `stock_locations`.`location_id`
LEFT JOIN `people`
ON `workschedule`.`employee_id` = `people`.`person_id`
WHERE
`stock_locations`.`location_id` = 1
OR (
AND `workschedule`.`checkedIn` = 1
AND `items`.`unit_price` != 0
AND `items`.`deleted` = 0
AND `stock_locations`.`deleted` = 0
NULL
)
You have LEFT JOIN, but your WHERE clause turns them into inner joins. Fixing that will probably fix your problem:
SELECT . . .
FROM item_quantities iq JOIN
stock_locations sl
ON iq.`location_id` = sl.`location_id` JOIN
items i
ON iq.`item_id` = i.`item_id` LEFT JOIN
workschedule ws
ON ws.`linked_storage` = sl.`location_id` AND
ws.`checkedIn` = 0 LEFT JOIN
--------^
people p
ON ws.`employee_id` = p.`person_id`
WHERE sl.`location_id` = 1 AND
i.`unit_price` != 0 AND
i.`deleted` = 0 AND
sl.`deleted` = 0

How do I select one row but no more from foreign key ? ---- Group BY ---

I have this statement that works fine without the below statement.
I think I may be using the incorrect statement. What I'm trying to do is only select the first productsapplied.applicationid. If another row has the same productsapplied.applicationid as one already selected it won't select it. There can be more than one of the same application id but I need it to only add 1.
DISTINCT('productsapplied'.applicationid)
'SELECT `productsApplied`.id, DISTINCT(`productsApplied`.applicationid)
FROM `productsapplied`
INNER JOIN `products`
ON `productsApplied`.productid = `products`.id
INNER JOIN `applications`
ON `productsApplied`.applicationid = `applications`.id
WHERE `applications`.clubid = ? AND `applications`.area = ? AND EXTRACT(YEAR FROM `applications`.date) = ? AND `products`.producttype = ?
If anyone has any ideas, would appreciate it!
If not I was thinking of just doing a COUNT DISTINCT
Lets say that here are the products applied
id: 3 clubid:6 applicationid: 5 ...
id: 4 clubid:6 applicationid: 5 ...
id: 5 clubid:6 applicationid: 5 ...
id: 4 clubid:6 applicationid: 6 ...
Presuming the rest of the statement holds e.g. year = ? etc..
Then the number of rows returned would be 2. AS there are 3 rows with the same application id. No matter how many rows there are with the same application id, one should be counted.
DISTINCT is applied is to whole row not to a single column for your concern there will be different productsApplied.ids per applicationid so you can grab all by using group_concat
SELECT
GROUP_CONCAT(pa.id),
`pa`.applicationid
FROM
`productsapplied` pa
INNER JOIN `products` p
ON `pa`.productid = `p`.id
INNER JOIN `applications` a
ON `pa`.applicationid = `a`.id
WHERE `a`.clubid = ?
AND `a`.area = ?
AND EXTRACT(YEAR FROM `a`.date) = ?
AND `p`.producttype = ?
GROUP BY `pa`.applicationid
If you are not concerned with productsApplied.ids then you can simple use the group by part but note group by without aggregate function will result in indeterminate order
Edit
This will give you one max id per applicationid
SELECT
SUBSTRING_INDEX(GROUP_CONCAT(pa.id ORDER BY pa.id DESC), 1),
`pa`.applicationid
FROM
`productsapplied` pa
INNER JOIN `products` p
ON `pa`.productid = `p`.id
INNER JOIN `applications` a
ON `pa`.applicationid = `a`.id
WHERE `a`.clubid = ?
AND `a`.area = ?
AND EXTRACT(YEAR FROM `a`.date) = ?
AND `p`.producttype = ?
GROUP BY `pa`.applicationid
or
SELECT
MAX(pa.id),
`pa`.applicationid
FROM
`productsapplied` pa
INNER JOIN `products` p
ON `pa`.productid = `p`.id
INNER JOIN `applications` a
ON `pa`.applicationid = `a`.id
WHERE `a`.clubid = ?
AND `a`.area = ?
AND EXTRACT(YEAR FROM `a`.date) = ?
AND `p`.producttype = ?
GROUP BY `pa`.applicationid
Select min(pa.id), pa.applicationid
From productsapplied pa
Join ...
...
Group by pa.applicationid

A Little Beyond Selecting Two Tables in MYSQL with PHP or a JOIN?

I'm trying to do a SELECT from two tables in the same db. This is what I'm trying...
SELECT * FROM Orders O
JOIN Employees_Packers EP
O.PackedBy AS EP.UserName
WHERE O.Shipped = 0 ORDER BY Order_ID
I'm trying to get this SELECT to give me all the rows where Shipped = 0 and have the EP.UserName value to show instead of the O.PackedBy. What am I missing?
EP.UserName = a Name Value
O.PackedBy = an Number
If O.PackedBy was also a string, this would work:
SELECT * FROM Orders O
JOIN Employees_Packers EP
ON O.PackedBy = EP.UserName
WHERE O.Shipped = 0 ORDER BY Order_ID
But I'm guessing that O.PackedBy is a Foreign Key to EP.ID (whatever the unique id field is named). Try substituting EP.UserName with EP.ID.
EDIT:
OK - given the comment below:
SELECT * FROM Orders O
JOIN Employees_Packers EP
ON O.PackedBy = EP.Packer_ID
WHERE O.Shipped = 0 ORDER BY Order_ID
This should join your two tables. SELECT * will give you all of the fields in both tables. If you only want EP.UserName in the result, replace the * with EP.Username.

Return 2 columns using subquerys in main query in mysql

I wish to populate a table on in a mysql database. Firstly I'd like to pull back all of the possibilities and them trim out the unrequired ones (easier than just adding them by hand).
The final table is:
combinations
combID
productID
type
content
exclude
extrafield2
extrafield6
The data comes from
extrafields_values
exvalueID
productID
extrafieldID
content
For each product I need to get return a row for each combination in extra_field_values (extrafieldID = 2 and extrafieldID = 6)
For instance:
productID = 700
extrafield2 = E, D, F
extrafield6 = 34,35,36,37
Returns the exvalueID to extrafields2 and 6 for each combination
So far I've tried:
SELECT EV.productID, extraFieldID, content AS extrafield6,
(SELECT content AS extrafield2
FROM wjf_extrafields_values AS EV2
INNER JOIN wjf_products AS P2
WHERE extraFieldID = 6) AS extrafield2
FROM wjf_extrafields_values AS EV
INNER JOIN wjf_products AS P ON P.productID = EV.productID
WHERE extrafieldID = 6
I believe you just need to link your wjf_products table to your extrafield_values table twice as shown below.
select p.productID, ev1.content as extrafield2, ev2.content as extrafield6
from wjf_products p inner join extrafields_values ev1 on p.productID = ev1.productID
inner join extrafields_values ev2 on p.productID = ev2.productID
where ev1.extraFieldID = 2
and ev2.extraFieldID = 6
Why not just create and use two views instead of a query.
View1 = Combinations
View2 = Subset of View1
Insert data using the View2