Basically, I have a two tables: management and pictures.
I need a list with all properties from the management table. If pictures exist, the list only has to show the first picture (seq=1).
My problem: the list doesn't show the properties without pictures. How do I solve this?
I have the following tables:
tblMan
propid | city | lang | ...
1 Mol NL
2 Olen NL
3 Geel NL
4 Ham FR
tblPic
propid | lang | seq | filename
1 NL 1 file11
1 FR 1 file12
1 NL 2 file13
1 FR 2 file14
1 NL 3 file15
1 FR 3 file16
3 NL 22 file17
3 FR 22 file18
3 NL 23 file19
3 FR 23 file20
3 NL 24 file21
3 FR 24 file22
SELECT m.propid, m.city, p.filename
FROM tblMan as m
INNER JOIN tblProp as p ON m.propid = p.propid
WHERE m.lang = 'NL' AND p.lang = 'NL' AND p.picture_index = '1'
The result is:
propid | city | filename
1 Mol file11
3 Geel file17
He doesn't get the propid 2 (Olen) because there is no image!
I want the result:
propid | city | filename
1 Mol file11
2 Olen (Null or 0 or...)
3 Geel file17
I tried subquery, union, concat... (#_#) with no result.
Does anybody has an idee what kind of SQL statement I should use?
Thanks for helping!
use LEFT JOIN since you want to display any records on table tblMan that matches your condition on the WHERE clause and move some filtering condition for table tblProp on the ON clause
SELECT m.propid,
m.city,
p.filename
FROM tblMan as m
LEFT JOIN tblProp as p
ON m.propid = p.propid
AND p.lang = 'NL'
AND p.picture_index = '1'
WHERE m.lang = 'NL'
Try this:
SELECT m.propid,
m.city,
p.filename
FROM tblman AS m
LEFT JOIN tblprop AS p
ON m.propid = p.propid
AND p.lang = 'NL'
AND p.picture_index = '1'
WHERE m.lang = 'NL'
You need to use LEFT OUTER JOIN in place of INNER JOIN.
Related
2 tables
product:
prod_id prod_name
1 Citrus-fruit
2 bread
3 margarine
4 Ready-Soup
5 Tropical-fruit
trans:
trans_id prod_1 prod_2 prod_3 prod_4
1 Citrus-fruit margarine Ready-Soup
2 bread margarine Tropical-fruit
3 Citrus-fruit bread margarine Tropical-fruit
4 bread Tropical-fruit
5 Citrus-fruit bread margarine Tropical fruit
So I want to compare prod_name = prod_1 and return prod_id, prod_name = prod_2 and return prod_id and so on
I tried a mysql query as
select product.prod_id from `product` ,'trans' where product.prod_name=trans.prod_1;
the above query doesn't work properly.
My expectation is:
prod_1 prod_2 prod_3 prod_4
1 3 4
2 3 5
1 2 3 5
2 5
1 2 3 5
and then convert above table into text file as:
1,3,4
2,3,5
1,2,3,5
2,5
1,2,3,5
Thank you
It is not clear what you are expecting.However, you can try that:
select * from product inner join trans on product.prod_name=trans.prod_1;
You should get back the elements that are matching.
If you want to translate the names with the products' ids, you will have to join the trans table with the product table once for each column
select p1.prod_id, p2.prod_id, p3.prod_id, p4.prod_id
from trans t1
left join
product p1
on t1.prod_1 = p1.prod_name
left join
product p2
on t1.prod_2 = p2.prod_name
left join
product p3
on t1.prod_3 = p3.prod_name
left join
product p4
on t1.prod_4 = p4.prod_name
order by t1.trans_id
The left join is required because in your sample table some products seem to be missing, so using inner joins would not return you all those rows with at least one product missing.
Edit
If you can't / don't want to add the commas at application level (which I would suggest) you can achieve the same by changing the query above like this
select trim(trailing ',' from concat_ws(',', coalesce(p1.prod_id, ''),
coalesce(p2.prod_id, ''),
coalesce(p3.prod_id, ''),
coalesce(p4.prod_id, '')
)
)
from trans t1
left join
product p1
on t1.prod_1 = p1.prod_name
left join
product p2
on t1.prod_2 = p2.prod_name
left join
product p3
on t1.prod_3 = p3.prod_name
left join
product p4
on t1.prod_4 = p4.prod_name
order by t1.trans_id;
You can see both version in action here
I have 2 tables :
Table 'annonce' (real estate ads) :
idAnnonce | reference
-----------------------
1 | dupond
2 | toto
Table 'freeDays' (Free days for all ads) :
idAnnonce | date
-----------------------
1 | 2015-06-06
1 | 2015-06-07
1 | 2015-06-09
1 | 2015-06-10
2 | 2015-06-06
2 | 2015-06-07
2 | 2015-06-12
2 | 2015-06-13
I want to select all alvailable ads who have only free days between a start and end date, I have to check each days between this date.
The request :
SELECT DISTINCT
`annonce`.`idAnnonce`, `annonce`.`reference`
FROM
`annonce`, `freeDays`
WHERE
`annonce`.`idAnnonce` = `freeDays`.`idAnnonce`
AND
`freeDays`.`date` = '2015-06-06'
AND
`freeDays`.`date` = '2015-06-07'
Return no result. Where is my error ?
It cant be equal both dates
SELECT DISTINCT a.idAnnonce, a.reference
FROM annonce a
INNER JOIN freeDays f ON a.idAnnonce = f.idAnnonce
WHERE f.date BETWEEN '2015-06-06' AND '2015-06-07'
What Matt is say is correct. You can also do this as alternative:
SELECT DISTINCT a.idAnnonce, a.reference
FROM annonce a
INNER JOIN freeDays f ON a.idAnnonce = f.idAnnonce
WHERE f.date IN('2015-06-06','2015-06-07')
Or like this:
SELECT DISTINCT a.idAnnonce, a.reference
FROM annonce a
INNER JOIN freeDays f ON a.idAnnonce = f.idAnnonce
WHERE f.date ='2015-06-06' OR f.date ='2015-06-07'
This will give you the same result as with an BETWEEN
Your WHERE clause is asking for the impossible!
You are asking for rows where the 'freedays'.'date' value is both 2015-06-06 and 2015-06-07.
AND
freeDays.date = '2015-06-06'
AND
freeDays.date = '2015-06-07'
You need to use BETWEEN:
freeDays.date BETWEEN '2015-06-06' AND '2015-06-07'
AND
freeDays.date = '2015-06-06'
OR
freeDays.date = '2015-06-07'
I have run into an issue. It is difficult to explain so I will place the example below:
MY TABLES:
region_hotelids
------------------------
EANHotelID | RegionID
------------------------
1234 935
2343 935
1234 850
hotel_attributes
------------------------
EANHotelID | AttributeID
------------------------
1234 1
1234 2
1234 4
1234 6
2343 1
2343 4
2343 2
2343 9
Now I first needed to find all the hotels with the same attributes:
SELECT r.EANHotelID, COUNT(c.EANHotelID) AS cat_count
FROM region_hotelid as r
INNER JOIN hotel_attributes AS c ON r.EANHotelID = c.EANHotelID
WHERE c.AttributeID IN (1,2) AND r.RegionID = 935
GROUP BY c.EANHotelID
HAVING cat_count = 2
This works beautifully and outputs this (finding all the EANHotelIDs containing these two attributeIDs):
result
EANHotelID | cat_count
---------------------------
1234 2
2343 2
Now the issue is, I need to get all the other attribute ids that these two hotels have in common. Which in this example would be only the AttributeID 4. I do not want any AttributeIDS that are not the same (in this example 9 and 6). This is what I came up with adding to the original query:
SELECT r.EANHotelID, COUNT(c.EANHotelID) AS cat_count,
(SELECT GROUP_CONCAT(c2.AttributeID) as ids
FROM hotel_attributes as c2
WHERE c2.EANHotelID = r.EANHotelID
AND c.EANHotelID = r.EANHotelID
GROUP BY c2.EANHotelID ORDER BY ids ASC ) as similarIds
FROM region_hotelid as r
INNER JOIN hotel_attributes AS c ON r.EANHotelID = c.EANHotelID
WHERE c.AttributeID IN (9,44) AND r.RegionID = 935
GROUP BY c.EANHotelID
HAVING cat_count = 2
But instead of only returning the id I want (4 or all of them - 1,2,4) it is returning all the AttributeIds associated with this EANHotelID:
result
EANHotelID | cat_count | similarIds
----------------------------------------
1234 2 1,2,3,4,6
2343 2 1,2,3,4,9
I am completely stumped on how to get past this. Any advice or information would be greatly appreciated!
You can use another INNER JOIN to select only the rows where all hotels have the same attributes. I moved the WHERE clause into the JOINs ON condition.
See a working SQL-Fiddle example here.
Note that your HAVING COUNT(..) condition is not performing well. The database engine has to examine each result set after the SELECT to see if your HAVING condition matches. I've left that untouched, but i think this should be optimized as well!
SELECT
ha.*
FROM
hotel_attributes ha
INNER JOIN hotel_attributes ha_other
ON
ha.AttributeID = ha_other.AttributeID
AND NOT ha.EANHotelID = ha_other.EANHotelID
AND ha_other.EANHotelID IN ( SELECT r.EANHotelID
FROM region_hotelids as r
INNER JOIN hotel_attributes AS c ON r.EANHotelID = c.EANHotelID
WHERE c.AttributeID IN (1,2) AND r.RegionID = 935
GROUP BY c.EANHotelID
HAVING COUNT(c.EANHotelID) = 2
)
GROUP BY ha.EANHotelID, ha.AttributeID
I know this question has already asked here, but I can't figure this one out from the previous answers.
We've got 2 tables:
members
-----------------------
| id | country_iso_3 |
-----------------------
1 USA
2 DZA
3 FRA
4 ILI
5 USA
6 USA
members_details
-----------------------
| member_id | city |
-----------------------
1 AA
2 BB
3 CC
4 DD
5 EE
6 FF
Now I want to query members_details and select the cities which are from the same countries, here "AA", "EE" and "FF" should be the results (because the members are from USA)
I know how to compare different cols from different tables, but here we need to check the second table 'member_id' and the first table 'id (country_iso_3)' somehow!
Select city from members LEFT JOIN members_details
ON members.id = members_details.memberid Where country_iso_3 = 'USA'
Just JOIN the two tables, with a WHERE clause for the country you want to get the city of it like so:
SELECT md.city
FROM members m
INNER JOIN members_details md ON m.id = md.memberid
WHERE m.country_iso_3 = 'USA'
SQL Fiddle Demo
This should work, and not only for USA, but for any country which is listed more than once:
SELECT d.city
FROM members m,
members_details d
WHERE d.member_id = m.id
AND m.country_iso_3 IN (
SELECT country_iso_3
FROM members
GROUP BY 1
HAVING count(1) > 1
)
Ok, I have an example table with the following information and query.
First up is the data, with the question following at the end.
Here's the SQL Dump:
http://pastie.org/private/o7zzajdpm6lzcbqrjolgg
Or you can use the included a visual below:
Purchases Table
| id | brand | date |
1 b1 2000-01-01
2 b1 2000-01-03
3 b2 2000-01-04
4 b3 2000-01-08
5 b4 2000-01-14
Owners Table
id | firstname | lastname | purchaseid | itemCoupon | itemReturned | Accessories
1 Jane Doe 1 yes no 4
2 Jane Doe 2 yes no 2
3 Jane Doe 3 no no 1
4 Jane Doe 4 no no 3
5 Jane Doe 5 no yes 6
The Query
SELECT brand, COALESCE( SUM( inTime.Accessories ) , 0 ) AS acessory_sum
FROM purchases
INNER JOIN owners AS person ON person.purchaseid = purchases.id
AND person.firstname = 'Jane'
AND person.lastname = 'Doe'
LEFT JOIN owners AS inTime ON person.id = inTime.id
AND purchases.date
BETWEEN DATE( '2000-01-01' )
AND DATE( '2000-01-05' )
GROUP BY purchases.brand
This gives the following expected result:
| brand | accessory_sum
b1 6
b2 1
b3 0
b4 0
The question
Now, I would like to add to the query:
WHERE itemCoupon = 'yes' OR itemReturned = 'yes'
But this overrides the last join and when I do the same search above I get:
| brand | accessory_sum
b1 6
b2 1
Similarly I still want it to return No results found for 2000-01-04, 2000-01-08 using WHERE itemCoupon = 'yes' OR itemReturned = 'yes'. Removing the WHERE gives me zeros for all brands if I try to do it another way.
Basically I want to keep the way the WHERE behaves but also keep the format that I described in the first example of the expected output.
As it is now, using WHERE destroys the way the last LEFT JOIN works with COALESCE which fills the remaining brand rows with zeros.
Your WHERE turns the outer join into an inner join.
You need to move your additionally condition into the LEFT JOIN condition:
LEFT JOIN owners as inTime
ON person.id = inTime.id
AND purchases.date between purchases.date DATE ('2000-01-01') and DATE ('2000-01-05')
AND (inTime.itemCoupon = 'yes' or inTime.itemReturned = 'yes')
the ON clause when doing a JOIN is similar to the WHERE clause. So instead of trying to use WHERE, just add another AND to your query (and don't forget to use the parenthesis in the OR clause):
SELECT brand,
COALESCE(SUM(Time.purchasedAccessories),0) as acessory_sum
FROM purchases
INNER JOIN owners AS person
ON person.purchaseid = purchases.id
AND person.firstname = 'Jane'
AND person.lastname = 'Doe'
AND (person.itemCoupon = 'yes' OR person.itemReturned = 'yes')
LEFT JOIN owners AS inTime
ON person.id= inTime.id
AND purchases.date
BETWEEN purchases.date
DATE( '2000-01-01' )
AND
DATE( '2000-01-05' )
GROUP BY purchases.brand