MySQL JOIN WHERE forgein Key = id1 AND forgein Key = id2 - mysql

I am having a bit of a brain block with this problem and I am finding it hard to search for a solution because I cant phrase the question correctly to bring up the relevant information.
I am trying to get back "fProduct" record from the table below where it has a "fAttribute"
of 2 and 20.
id fAttribute fProduct
19 2 2967
48 2 2923
50 2 3008
51 20 3008
52 2 2295
53 20 2295
My statment below produces 0 results when I would expect to return fProduct's 2295 and 3008.
SELECT fProduct
FROM tableName
WHERE fAttribute = 2 AND fAttribute = 20
GROUP BY fProduct
Can anyone help please?

You can either use INNER JOINS or use EXISTS conditions:
INNER JOIN:
SELECT DISTINCT a.fProduct
FROM MyTable a
INNER JOIN MyTable b ON a.fProduct = b.fProduct AND b.fAttribute = 2
INNER JOIN MyTable c ON a.fProduct = c.fProduct AND c.fAttribute = 20
EXISTS:
SELECT afproduct
FROM MyTable a
WHERE EXISTS (SELECT b.id FROM MyTable b WHERE a.fProduct = b.fProduct AND b.fAttribute = 2)
AND EXISTS (SELECT c.id FROM MyTable c WHERE a.fProduct = c.fProduct AND c.fAttribute = 20)

A join should help:
SELECT distinct a.fProduct
FROM tableName as a
join tableName as b on b.product = a.product
WHERE a.fAttribute = 2 and b.fAttribute = 20

Since your are already doing a GROUP BY just change your WHERE clause to an OR or an IN and add the HAVING COUNT(fattribute) = 2 which makes sure it has both.
SELECT fproduct
FROM tablename
WHERE fattribute IN (2 , 20)
GROUP BY fproduct
HAVING COUNT(fattribute) = 2

Related

How group values in Mysql query?

I have query:
SELECT p.`obj_id` ,
p.`alt_name` ,
o.`name`,
p.`id`,
oc.`text_val`,
oc.`float_val`
FROM `cms3_hierarchy` p
LEFT JOIN `cms3_objects` o
ON p.`obj_id` = o.`id`
LEFT JOIN `cms3_object_content` oc
ON p.`obj_id` = oc.`obj_id`
WHERE (oc.`field_id` = 221 OR oc.`field_id` = 248 )
AND (p.`rel`=903687) LIMIT 0,50
But answer like this:
obj_id name id 221 248
1 first 2 null
1 first null 3
Well, i have one obj_id with different values.
But for me this is look like this:
obj_id name id 221 248
1 first 2 3
How to do this?
Conditions on the right table of a LEFT JOIN should be specified only inside the ON clause, when they are in the WHERE clause, the join automatically turns into an INNER JOIN because of NULL comparison.
Also, use IN() to compare the same column to multiple values instead of OR . I also used MAX() to group the rows into one row, so :
SELECT p.obj_id , p.alt_name , o.name,p.id,
MAX(CASE WHEN oc.field_id = 221 THEN oc.text_val END) as col_221,
MAX(CASE WHEN oc.field_id = 1123 THEN oc.text_val END) as col_1123,
MAX(oc.float_val)
FROM cms3_hierarchy p
LEFT JOIN cms3_objects o
ON p.obj_id = o.id
LEFT JOIN cms3_object_content oc
ON p.obj_id = oc.obj_id and oc.field_id in(221,248,1123)
WHERE p.rel=903687
LIMIT 0,50
GROUP BY p.obj_id , p.alt_name , o.name,p.id

How can I accomplish the following in SQL?

I have two tables.
table_a:
id | data_x | data_y
--------------------
1 person joe
2 person bob
3 amount 200
4 addres philville
tableB:
map_id | table_a_id
-------------------
7 1
7 3
7 4
8 4
8 2
The result I want is the map_id if it has an entry in table_a for both data_x = 'person' and data_y = '200'
So with the above table B, the result should be
map_id
------
7
How can I write that query in SQL?
This situation is a perfect fit for an unusual SQL operator: INTERSECT. It is a very declarative, efficient and elegant solution for this problem.
SELECT Map.map_id
FROM Table_B AS Map JOIN Table_A AS Person ON (Person.id = Map.table_a_id) AND (Person.data_x = 'person')
INTERSECT
SELECT Map.map_id
FROM Table_B AS Map JOIN Table_A AS Amount ON (Amount.id = Map.table_a_id) AND (Amount.data_y = '200')
Formally what you are asking for is exactly the intersection of two disjoint sets: the set of map id's that are persons and the set of map id's that have a value of 200.
Please note the INTERSECT operator does not exists in MySQL, but it does in almost all advanced relational DBMS, including PostgreSQL.
This is less elegant than the INTERSECT solution #Malta posted, but it works with the limited capabilities of MySQL as well:
SELECT b1.map_id
FROM table_a a1
JOIN tableb b1 ON a1.id = b1.table_a_id AND a1.data_x = 'person'
JOIN tableb b2 ON b2.map_id = b1.map_id AND b2.table_a_id <> b1.table_a_id
JOIN table_a a2 ON a2.id = b2.table_a_id AND a2.data_y = '200';
SQL Fiddle for MySQL.
SQL Fiddle for Postgres.
Based on your input, the following should get you started using MySQL:
SELECT
map_id
FROM TableB
JOIN Table_A
ON TableB.table_a_id = Table_A.id
AND
((Table_A.data_x = 'person')
OR
(Table_A.data_y = '200')
)
GROUP BY map_id
HAVING COUNT(table_a_id) = 2
;
See it in action: SQL Fiddle.
Update
As Erwin Brandstetter made explicit: If the data can't be trusted to be inherently consistent (along the lines of your inquiry), one option is:
SELECT map_id FROM (
SELECT map_id, 'data_x' t
FROM TableB B JOIN Table_A A ON B.table_a_id = A.id AND A.data_x = 'person'
UNION
SELECT map_id, 'data_y'
FROM TableB B JOIN Table_A A ON B.table_a_id = A.id AND A.data_y = '200'
) T
GROUP BY map_id
HAVING COUNT(DISTINCT t) = 2
;
This should ensure "at least one each". (Alternatives have been suggested by others.) To get "exactly one each", you could try
SELECT map_id FROM (
SELECT map_id, 'data_x' t, data_y
FROM TableB B JOIN Table_A A ON B.table_a_id = A.id AND A.data_x = 'person'
UNION
SELECT map_id, 'data_y', data_y
FROM TableB B JOIN Table_A A ON B.table_a_id = A.id AND A.data_y = '200'
) T
GROUP BY map_id
HAVING COUNT(DISTINCT t) = 2 AND COUNT(DISTINCT data_y) = 2
;
See it in action (with additional test data): SQL Fiddle.
And it works in PostgreSQL as well: SQL Fiddle
Please comment if and as this requires adjustment / further detail.
Join the 2 tables, group by map_id, use conditional counting with either count() or sum(), and filter in having clause (I use mysql syntax below):
select map_id,
sum(
case
when a.data_x='person' or a.data_y='200' then 1
else 0
end
) as matches
from a
inner join b on a.id=b.a_id
group by b.map_id
having matches=2
The above query assumes that you cannot have more than one record for any map_id where data_x is person or data_y is 200. If this assumption is incorrect, then you need to use either exists subqueries or 2 derived tables.
Sounds like you want a standard INNER JOIN.
But I do beg to differ on your result:
map_id if it has an entry in table_a for both data_x = 'person' and data_y = '200'
There is not a record in your data set that has both 'person' and data_y = '200' and therefore no mp_id can be returned
Here is a typical INNER JOIN relating to your narrative.
SELECT DISTINCT
b.map_id
FROM
TableA a
INNER JOIN TableB b
ON a.id = b.table_a_id
WHERE
a.data_x = 'person'
AND a.data_y = '200'
If more than one map_id exists with data_x = 'person' and data_y = '200' then you will get multiple results but only 1 row per map_id
If you want the map_id(s) for records with data_x = 'person' or data_y = '200' then switch the and in the where statement to or and you will receive map_id 7 & 8.
SELECT DISTINCT
b.map_id
FROM
TableA a
INNER JOIN TableB b
ON a.id = b.table_a_id
WHERE
a.data_x = 'person'
OR a.data_y = '200'
Note this encompasses (7,1)(8,2) because 1 & 2 both have data_x = 'person' and then (7,3) because 3 has data_y = '200' therefore it would return map_id 7 & 8.
select map_id from
table_b b
left outer join table_a a1 on (b.table_a_id = a1.id and a1.data_x = 'person')
left outer join table_a a2 on (b.table_a_id = a2.id and a2.data_y = '200')
group by map_id
having count(a1.id) > 0 and count(a2.id) > 0
Lets do it simple:
SELECT * FROM
(
SELECT map_id
FROM table_a a1
inner join TableB b1 ON a1.id = b1.table_a_id
where a1.data_x = 'person'
) as p
inner join
(
SELECT map_id
FROM table_a a1
inner join TableB b1 ON a1.id = b1.table_a_id
where a1.data_y = '200'
) as q
on p.map_id = q.map_id
You may replace SELECT * FROM with SELECT p.map_id FROM.
You may add more sub-set-joins to have more conditions.
sql-fiddle

WHERE [1 of these values] IN [1 of these values]

I have the following query :
SELECT A.id FROM logsen_alertes A
WHERE
( SELECT LA2.type_colocation_id
FROM logsen_liaisons_annonces_types_colocations LA2
WHERE LA2.annonce_id = 25 AND LA2.annonce_type = 4
)
IN
( SELECT L4.souhait
FROM logsen_liaisons_alertes_souhaits L4
WHERE L4.alerte_id = A.id
)
This query works well when my first subquery returns only 1 value, because that's how works IN(), looking for 1 unique value in a set of values. When my 1st subquery returns 2 or more values, MySQL returns me "Subquery returns more than 1 row". How can I make my query works when the first subquery returns several values ? Something like "WHERE [any of these values] i found in [ny of these values]" ?
Try:
SELECT DISTINCT A.id FROM logsen_alertes A
JOIN logsen_liaisons_alertes_souhaits L4 ON L4.alerte_id = A.id
JOIN logsen_liaisons_annonces_types_colocations LA2
ON LA2.type_colocation_id = L4.souhait AND LA2.annonce_id = 25 AND LA2.annonce_type = 4
Try this:
SELECT
A.id
FROM
logsen_alertes A
INNER JOIN logsen_liaisons_alertes_souhaits L4
ON L4.alerte_id = A.id
INNER JOIN logsen_liaisons_annonces_types_colocations LA2
ON LA2.type_colocation_id = L4.souhait
WHERE
LA2.annonce_id = 25 AND LA2.annonce_type = 4
SELECT DISTINCT A.id FROM logsen_alertes AS A
INNER JOIN logsen_liaisons_alertes_souhaits AS L4
ON (L4.alerte_id = A.id)
INNER JOIN logsen_liaisons_annonces_types_colocations AS LA2
ON (LA2.type_colocation_id = L4.souhait)
WHERE LA2.annonce_id = 25 AND LA2.annonce_type = 4
Should work

MySQL JOIN 3 tables in one query

Could you please help me to make this query works
SELECT *
FROM `SC_orders`
LEFT JOIN `SC_customer_reg_fields_values` using(customerID)
WHERE (`statusID` = 2 OR `statusID` = 3 OR `statusID` = 21 OR `statusID` = 25 OR `statusID` = 26) AND DATE(order_time) > '2012-12-01 00-00-00'
LEFT JOIN `SC_ordered_carts`
ON orderID = orderID
GROUP BY orderID
I try to combine information from 3 tables in one output. This query works fine without last LEFT JOIN and Grouping. Where is my mistake?
The where needs to be after the last join. also, the second ON clause is ambiguous and I think the group by is unnecessary since you don't have any aggregate functions:
SELECT *
FROM `SC_orders`
LEFT JOIN `SC_customer_reg_fields_values` using(customerID)
LEFT JOIN `SC_ordered_carts` using(orderID)
WHERE (`statusID` = 2 OR `statusID` = 3 OR `statusID` = 21 OR `statusID` = 25 OR `statusID` = 26) AND DATE(order_time) > '2012-12-01 00-00-00'

MySQL query returning 0 rows while it should return one

Something is wrong with my MySQL query below but I can't find the problem. It's not returning any errors but the query below should return 1 row, but it returns none.
The table 'fws_product' contains all products. The table 'webits_product_has_kenmerken' contains the product specifications.
SELECT fws_product.*
FROM webits_product_has_kenmerken
LEFT JOIN fws_product ON webits_product_has_kenmerken.product_id = fws_product.ID
WHERE fws_product.CATID = 11
AND (
(webits_product_has_kenmerken.kenmerk_id = 8 AND webits_product_has_kenmerken.kenmerk_value = 'Buddha to Buddha')
AND
(webits_product_has_kenmerken.kenmerk_id = 19 AND webits_product_has_kenmerken.kenmerk_value = '10 mm')
)
Thanks in advance!
It looks a bit nasty, but the following should do as you have requested
SELECT
p.*
FROM fws_product AS p
INNER JOIN webits_product_has_kenmerken AS ps8
ON ps8.product_id = p.ID
AND ps8.kenmerk_id = 8
AND ps8.kenmark_value = 'Buddha to Buddha'
INNER JOIN webits_product_has_kenmerken AS ps19
ON ps19.product_id = p.ID
AND ps19.kenmerk_id = 19
AND ps19.kenmark_value = '10 mm'
WHERE p.CATID = 11
This is another potential option which may do the job, but still feels very nasty
SELECT
p.*
FROM fws_product AS p
INNER JOIN (
SELECT
product_id,
COUNT(*) AS numMatches
FROM webits_product_has_kenmerken
WHERE (kenmerk_id,kenmerk_value) IN (
(8,'Buddha to Buddha'),
(19,'10 mm')
)
GROUP BY product_id
HAVING numMatches = 2
) AS ps
ON ps.product_id = p.ID
WHERE p.CATID = 11
i think you need the following:
SELECT fws_product.*
FROM webits_product_has_kenmerken
LEFT JOIN fws_product ON webits_product_has_kenmerken.product_id = fws_product.ID
WHERE fws_product.CATID = 11
AND (
(webits_product_has_kenmerken.kenmerk_id = 8 AND webits_product_has_kenmerken.kenmerk_value = 'Buddha to Buddha')
OR
(webits_product_has_kenmerken.kenmerk_id = 19 AND webits_product_has_kenmerken.kenmerk_value = '10 mm')
)
checke these columns for NULL values:
fws_product.CATID
webits_product_has_kenmerken.kenmerk_id
webits_product_has_kenmerken.kenmerk_value
every comparison with NULL will exclude the row from the reult