Query on two tables merged with same column names - mysql

I have these tables in my MySQL database:
BUYERS
ID|SELLER
----------------
0 |Paul
1 |Jean
2 |David
3 |Jack
4 |John
5 |Fred
6 |Peter
PARIS
ID|CAR
---------
0 |Toyota
1 |BMW
2 |Honda
LONDON
ID|CAR
---------
3 |Ford
4 |BMW
5 |Honda
6 |Honda
I use the followinq query :
SELECT b.id, b.seller, p.car
FROM buyers b
JOIN paris p
ON b.id = p.id
UNION ALL
SELECT b.id, b.seller, l.car
FROM buyers b
JOIN london l
ON g.id = l.id;
To get the following result :
ID|SELLER |CAR
----------------
0 |Paul |Toyota
1 |Jean |BMW
2 |David |Honda
3 |Jack |Ford
4 |John |BMW
5 |Fred |Honda
6 |Peter |Honda
I wanted to retrieve rows with "Honda" as "CAR" and I Tried to append the query with "Where car = 'Honda'" but without success..
Thanks for any help

Adding
WHERE car = 'Honda';
to your query only refers to the second query, i.e. the one after UNION ALL.
So either:
SELECT b.id, b.seller, p.car FROM buyers b JOIN paris p ON b.id = p.id
WHERE p.car = 'Honda'
UNION ALL
SELECT b.id, b.seller, l.car FROM buyers b JOIN london l ON b.id = l.id
WHERE p.car = 'Honda'
;
or
SELECT id, seller, car
FROM
(
SELECT b.id, b.seller, p.car FROM buyers b JOIN paris p ON b.id = p.id
UNION ALL
SELECT b.id, b.seller, l.car FROM buyers b JOIN london l ON b.id = l.id
) data
WHERE car = 'Honda';

Just appending WHERE car = 'Honda' is ambiguous. Which car column should be checked?
The easiest way to achieve this is to wrap your existing query within another select statement so that the query is applied on the resulting table, i.e.
SELECT * FROM
(
SELECT b.id, b.seller, p.car
FROM buyers b
JOIN paris p
ON b.id = p.id
UNION ALL
SELECT b.id, b.seller, l.car
FROM buyers b
JOIN london l
ON g.id = l.id;
)
WHERE car = 'Honda'

Can you please try below query:
select * from (
SELECT b.id, b.seller, p.car
FROM buyers b
JOIN paris p
ON b.id = p.id
UNION ALL
SELECT b.id, b.seller, l.car
FROM buyers b
JOIN london l
ON g.id = l.id;
)
where car = 'HONDA'

This is not an answer, but mere advice.
Just in case this is your real database (I'm pretty sure it isn't), here is some advice:
The table names tell us what entities you are dealing with. In your database this is buyers, parises, and londons. You probably see your mistake ;-)
Then looking into the buyers table we see the main column is called seller. What the heck? Is it buyer or seller?
Then a column called ID should be the table's ID and uniquely identify a record in the table. You, however, are using the buyers IDs in other tables and still call them ID.
In your example each buyer has only one other record either in London or in Paris. If this is the case, then you can simply make the car a column in the buyers table instead. If you do need an n:m relation, then call the IDs by what they are, i.e. buyer_id or the like.
In any case there should be a car table containing one record per car, in order to avoid misspellings like 'Homda' in some records.
You are showing car brands, but call the table cars. If it's really about brands only, a better name would hence be brands or car_brands or the like.
Here is an example on how to design the database:
Cars
id_car | name
-------+-------
1 | BMW
2 | Ford
3 | Honda
4 | Toyota
Sellers
id_seller | name
----------+------
0 | Paul
1 | Jean
2 | David
3 | Jack
4 | John
5 | Fred
6 | Peter
Sellers_Cars
id_seller | id_car
----------+-------
0 | 1
0 | 2
0 | 4
1 | 1
2 | 3
3 | 2
4 | 1
5 | 3
6 | 3
6 | 4
A possible query:
select name as honda_seller
from sellers
where id_seller in
(
select id_seller
from sellers_cars
where car_id = (select car_id from cars where name = 'Honda')
);

Related

Multiple rows with 2 condition in the same column MySQL

How to select multiple rows with 2 condition in the same column MySQL
students' table:
id name
1 Jhon
2 Anne
3 Charles
4 Bob
lesson_contract's table:
id lesson_code student_id
1 L1 1
2 L2 1
3 L1 2
4 L1 3
5 L2 3
6 L2 4
So i want to get student that take both lesson_code L1 and L2. So the result should be Jhon and Charles
You could do this by joining into the lesson_contract table twice, once for each lesson code:
SELECT s.id, s.name FROM students s
INNER JOIN lesson_contract l1
ON s.id = l1.student_id AND l1.lesson_code = 'L1'
INNER JOIN lesson_contract l2
ON s.id = l2.student_id AND l2.lesson_code = 'L2'
Inner joins will filter the results, so you'll only get rows where both join conditions were met.
You must join the tables, group by name and put the condition in the having clause:
select s.name
from student s inner join lesson_contract l
on l.student_id = s.id
where l.lesson_code in ('L1', 'L2')
group by s.name
having count(distinct l.lesson_code) = 2
You may remove distinct if there is no case for a student to take the same lesson twice.
See the demo.
Results:
| name |
| ------- |
| Charles |
| John |

Select things from three different tables with inner join

Well, I have three tables:
Cart:
ID | Product | Quantity
1 S1FG 3
1 C0K0 1
1 SLM1 6
2 S1FG 2
2 S94A 2
Products:
Code | Price
S1FG 10.00
C0K0 8.00
SLM1 19.50
S94A 2.00
And Users:
ID | Nickname
1 Mark
2 Steve
I want this:
Nickname | Products | Total
Mark 10 155.00
Steve 4 24.00
In words, I want a list of users that has something in Cart, a count of their items and a sum of the prices of their items.
I tried this:
SELECT DISTINCT b.Nickname, SUM(a.Quantity) as Products, SUM(a.Quantity*c.Price) as Total
FROM Cart a
INNER JOIN Users b ON (a.ID = b.ID)
INNER JOIN Products c ON (a.Product = c.Code)
But it didn't work...
What can I do?
You need to GROUP BY the nickname or you'll just get a single line:
SELECT DISTINCT b.Nickname, SUM(a.Quantity) as Products, SUM(a.Quantity*c.Price) as Total
FROM Cart a
INNER JOIN Users b ON (a.ID = b.ID)
INNER JOIN Products c ON (a.Product = c.Code)
GROUP BY b.Nickname

SQL - Join 3 tables little confusing

I need a help about a little confusing sql query. I have 3 tables. Names : article, category and category_article table.
In my article table, there are 4 columns which are :
aid -> article id
py -> Year of article
totalPoint -> point of Article
tc -> number of cited of article
In category table, there are 2 columns which are :
cid -> category id
category -> name of category
Lastly, in my category_article table, there are 2 columns which are :
cid -> category id
aid -> article id related with category
In the below, there are sample table inputs.
Article Table
______________________________
| aid | py | totalPoint | tc |
-------------------------------
| 1 | 2014| 30 | 3 |
-------------------------------
| 2 | 2013| 20 | 2 |
-------------------------------
| 3 | 2014| 50 | 10 |
_______________________________
Category Table
__________________
| cid | category |
-------------------
| 1 | Surgery |
-------------------
| 2 | Enginering|
____________________
Category_Article Table
__________________
| cid | aid |
-------------------
| 1 | 3 |
-------------------
| 2 | 5 |
____________________
My purpose is find this output with only one sql query.
Category name, year, totalArticleNumber, totalPoint(desc), id of article(the most cited article at that year and at that category), citedTime (Top 20)
The example output is :
_______________________________________________________________________________________
Category name | year | totalArticleNumber | totalPoint | id of article(best) | citedTime |
________________________________________________________________________________________
Surgery | 2013 | 182 | 5234 | 312 | 22 |
_________________________________________________________________________________________
Engineering | 2014 | 189 | 5000 | 10 | 32 |
I can do this table with java programing language. Like first do some query and after that do it second query.
But i need to do it in one query.
I try to use JOIN , HAVING , GROUP BY , DISTINCT and anaother some sql stuff but i cannot succeed.
Any help is appreciated.
EDIT
For example if there are two article with same time cited value, they are shown together.
Like in first two column, the article 419 and 385 same time cited value so they both in table.
There are two options for me.
First way -> Show only one article and limit 20. So in this way i can see 20 different category-year combination.
Second way -> Show the same value timecited articles but i have to see 20 different category-year combination.
This is a little tricky, because you're trying to do a lot of different things here. I would simply break them down and put them back together. First, if you want to JOIN all the tables together, you can use the following syntax:
SELECT *
FROM article a
JOIN category_article ca ON ca.aid = a.aid
JOIN category c ON c.cid = ca.cid;
Now, this will only show articles that are assigned to a category. In other words, if an article doesn't exist in the category_article table, or a category doesn't exist in the category_article table, it won't appear here.
If you want to get the total number of articles for a category per year, you can use the COUNT(*) aggregate function, and the SUM() function to get the total points for that category, and then group by category and year to get the amounts for that group:
SELECT c.category, a.py, COUNT(*) AS numArticles, SUM(totalPoint) AS totalPoints
FROM article a
JOIN category_article ca ON ca.aid = a.aid
JOIN category c ON c.cid = ca.cid
GROUP BY c.cid, a.py;
Next, getting the best article will have to be done using a subquery. I recommend focusing just on that subquery for a moment. You can write one query to get the MAX tc for each category and year, and then join that with your table to get all the matching conditions, like this:
SELECT c.category, a.*
FROM category c
JOIN category_article ca ON c.cid = ca.cid
JOIN article a ON a.aid = ca.aid
JOIN(
SELECT c.cid, a.py, MAX(a.tc) AS maxCited
FROM category c
JOIN category_article ca ON ca.cid = c.cid
JOIN article a ON a.aid = ca.aid
GROUP BY c.cid, a.py) temp ON temp.cid = c.cid AND temp.py = a.py AND temp.maxCited = a.tc;
Once you have that, you can JOIN that subquery with the query above to show the best article information alongside the other group information.
SELECT temp1.category, temp1.py, temp1.numArticles, temp1.totalPoints, temp2.aid AS bestArticle, temp2.tc AS citedTime
FROM(
SELECT c.category, a.py, COUNT(*) AS numArticles, SUM(totalPoint) AS totalPoints
FROM article a
JOIN category_article ca ON ca.aid = a.aid
JOIN category c ON c.cid = ca.cid
GROUP BY c.cid, a.py) temp1
JOIN(
SELECT c.category, a.*
FROM category c
JOIN category_article ca ON c.cid = ca.cid
JOIN article a ON a.aid = ca.aid
JOIN(
SELECT c.cid, a.py, MAX(a.tc) AS maxCited
FROM category c
JOIN category_article ca ON ca.cid = c.cid
JOIN article a ON a.aid = ca.aid
GROUP BY c.cid, a.py) temp ON temp.cid = c.cid AND temp.py = a.py AND temp.maxCited = a.tc) temp2
ON temp1.category = temp2.category AND temp1.py = temp2.py;
Here is an SQL Fiddle example. I am going to play around with how to use fewer JOINS, but for right now it should give you what you want and since your tables are indexed it shouldn't run too slowly.

MySQL: Limit Results related to FROM with Joins that have multiple subelements

I habe a main table that i select from and a table with subelements that i select from in a join. Example:
person skill person_to_skill
id | name id | skill id | p_id | s_id
------------ ------------ ----------------
1 | jim 1 | sewing 1 | 1 | 2
2 | peter 2 | cooking 2 | 2 | 1
3 | susan 3 | singing 3 | 2 | 3
4 | kevin 4 | 3 | 1
5 | 3 | 2
6 | 4 | 3
So now we see, sim has only one skill, peter has two and so forth.
Now if i select from person, koin skill and then also join person_to_skill, but i only want two persons. How do i manage to do so without grouping and thereby not getting all the skills?
Shortly: I want to select two persons from "person" with all their skills.
I tried just using LIMIT but that limits the result rows, not the persons.
If i use GROUP BY i only get one skill per person.
Is this possible without a subselect?
Any ideas anyone?
My Approach so far, changed to work with the example, looks like this:
SELECT p.id,p.name,s.skill
FROM person AS p
LEFT JOIN person_to_skill psk ON (psk.p_id = p.id)
LEFT JOIN skill s ON (s.id = psk.s_id)
ORDER BY p.name
LIMIT 0,2
Limit number of persons at very beginning in subquery then join to them other tables as you've already done:
SELECT p.id,p.name,s.skill
FROM (select * from person ORDER BY name LIMIT 0,2) AS p
LEFT JOIN person_to_skill psk ON (psk.p_id = p.id)
LEFT JOIN skill s ON (s.id = psk.s_id)
Added after comment:
If you really can't use subqueries you can do it using two queries. Firstly select users ids:
select id from person ORDER BY name LIMIT 0,2
and then use those ids in next query:
SELECT p.id,p.name,s.skill
FROM person p
LEFT JOIN person_to_skill psk ON (psk.p_id = p.id)
LEFT JOIN skill s ON (s.id = psk.s_id)
WHERE p.id IN (ids from previous query)
You can do something like
SELECT p.id, p.name, group_concat(s.skill separator ',')
and then group by person and limit the number of rows.

JOIN bills ON bills.item_id = cars.id

There are two tables:
TABLE bills
item_id | price
c1 | 10000
m1 | 9000
m2 | 8000
TABLE cars
id | model
1 | toyota
2 | bmw
I need JOIN both tables, where item_id=id AND the first letter in item_id is 'c', so I need to get: c1 | 10000 | 1 | toyota
select *
from cars c
join bills b on b.item_id = concat('c', c.id)
Note that performance is orders of magnitude better (and acceptable) joining in this order, because the calculation to generate the composite key is done once per car, rather than once per car/bill combination had I joined bills first then cars.
Do it like this:
select b.*, c.*
from bills b
inner join cars c on convert(substring(b.item_id, 2, 8000), int) = c.id
where b.item_id like 'c%'