I have one table for workers and an other for offices. One worker can be in different offices or in any.
The tables are like:
**Workers**
ID | Name
1 | Ned
2 | James
3 | Tyrion
**WorkersOffices**
WorkerID | OfficeID
1 | 18
1 | 17
2 | 18
I want to join the two tables to get something like this:
**Joined**
ID | Name | OfficeID
1 | Ned | 18
1 | Ned | 17
2 | James | 18
3 | Tyrion |
I have tried the following but it only join one office for worker.
SELECT * FROM workers w
LEFT JOIN workersoffice wo on w.id = wo.workerid
How can I obtain this result?
You have to use LEFT JOIN for that:
SELECT * FROM workers w
LEFT JOIN workers_office wo on w.id = wo.worker_id
Which will basically take all the rows from workers table and join office, if it exists for that worker.
Another thing to mention which is not related to the question is to use a singular name of the tables, you can read more about it in this SO answer
This is what you need:
select w.id,w.name,wo.office_id from workers w left join WorkerOffices wo on w.id = wo.worker_id;
Result set:
+------+--------+-----------+
| id | name | office_id |
+------+--------+-----------+
| 1 | Ned | 18 |
| 1 | Ned | 17 |
| 2 | James | 18 |
| 3 | Tyrion | NULL |
+------+--------+-----------+
#Uri Your query after join just use "group by workers I'd or name".
It will definitely help you in this. And your join is correct. Then you will b egg able to get no of locations of workers.
Related
I wanted to learn about web development so I made website with where users can vote on movies, and have issues with making a query for what I need. My tables are as follows:
--rtable--
+-----------+------------+------------+
| movieid | rating | userid |
+-----------+------------+------------+
| 1 | 9 | 27 |
| 2 | 8 | 27 |
| 1 | 10 | 31 |
| 1 | 7 | 42 |
| 2 | 8 | 31 |
+-----------+------------+------------+
--mtable--
+-----------+------------+------------+------------+
| movieid | moviename | movielink | director |
+-----------+------------+------------+------------+
| 1 | Foo | foo.com | bob |
| 2 | Bar | bar.com | steve |
+-----------+------------+------------+------------+
I wanted to make a query to for movie name, movie link, avg(rating), and the users rating (if exists), descending by avg(rating)
--desiredtable (if userid == 42)--
+-----------+------------+------------+------------+
| moviename | movielink | avgrating | yourrating |
+-----------+------------+------------+------------+
| Foo | foo.com | 8.66 | 7 |
| Bar | bar.com | 8 | NULL |
+-----------+------------+------------+------------+
I've managed to get moviename + movielink + avgrating working with OUTER LEFT JOIN but I'm scratching my head as to how to add yourrating. I've tried doubling up on OUTER JOIN and using sub-queries but can't seem to get it to work.
This is what I have so far that works
SELECT mtable.moviename, mtable.movielink, ROUND(AVG(rtable.rating), 2) AS avgrating,
FROM mtable LEFT OUTER JOIN rtable ON rtable.movieid = mtable.movieid GROUP BY mtable.charid ORDER BY AVG(rtable.rating) DESC
You need to join the rtable twice on the mtable, once to get all ratings for the average, once to get the user's rating. You also need to supply the userid for which r2 is filtered within the on clause. That filter criterion in the on clause will apply to r2 only, not the entire dataset.
SELECT mtable.moviename, mtable.movielink, ROUND(AVG(r1.rating), 2) AS avgrating, max(r2.rating) as yourrating
FROM mtable m LEFT OUTER JOIN rtable r1 ON r1.movieid = m.movieid
LEFT JOIN rtable r2 on r2.movieid=m.movieid and r2.userid=...
GROUP BY m.movieid, m.moviename, m.movielink
ORDER BY AVG(r1.rating) DESC
I have the needing to chain some joins queries, and I am not able to get the result that I want.
I have many tables to save some product info:
-Products: Name and description in many languages.
-Products_attributes: Some common attributes of the products like the provider or the buying price.
-Products_locations: Info concerning the locations that sell a certain product, like stock, or the selling price.
-Other important table is the Companies one: some of this companies could be a provider.
Well, this is my query:
SELECT p.id
, p.name nameProduct
, p.reference refProduct
, a.buy_price priceProduct
, l.active
, l.sell_price
, l.stock stockProduct
, c.title p_name
FROM products p
LEFT JOIN products_location l
ON l.product_reference = p.reference
AND l.active = 1
AND l.location_id = 4
JOIN products_attributes a
ON a.product_reference = p.reference
AND p.lang = 'es'
AND a.provider = 6
JOIN companies c
ON a.provider = c.id
AND c.id = 6
What I want to do is get all products of a certain provider, if the location from where is executing the query has this product, the row of the result must return too the concerning at this product<->location, in contrary it must return NULL in the column related to this relation.
At the moment, with this query, all what I am getting is the products of a provider where has a relation between the product<->location (through products_location table).
Any way to do that??
Thank you.
EDIT
An example about what I trying to get could be something like this:
TABLE: Companies
id | Title
1 | SomeName
6 | ProviderName
TABLE: Products
id | reference | name | lang
1 | 11111 | 1_es | es
2 | 11111 | 1_en | en
3 | 22222 | 2nam | es
4 | 33333 | 3nam | es
5 | 44444 | 4nam | es
6 | 55555 | 5nam | es
TABLE: Products_atributte
id | product_reference | buy_price | provider
1 | 11111 | 10 | 6
1 | 22222 | 15 | 6
1 | 33333 | 20 | 6
1 | 44444 | 12 | 1
1 | 55555 | 13 | 1
TABLE: Products_locations
id | product_reference | location_id | sell_price | stock | active
1 | 11111 | 4 | 26 | 10 | 1
1 | 11111 | 5 | 25 | 13 | 1
1 | 22222 | 5 | 20 | 13 | 1
1 | 44444 | 5 | 21 | 1 | 1
1 | 55555 | 5 | 22 | 2 | 1
AND THE RESULT MUST BE SOMETHING LIKE THIS:
nameProduct | refProduct | priceProduct | active | sell_price | stockProduct | p_name
1_es | 11111 | 10 | 1 | 26 | 10 | ProviderName
2nam | 22222 | 15 | NULL | NULL | NULL | ProviderName
3nam | 33333 | 20 | NULL | NULL | NULL | ProviderName
If I use a LEFT JOIN only in the products_locations table, I donĀ“t get the two last rows, and if I use LEFT JOIN with all the tables I get duplicates product references, also I get products provided by other providers (in the example 1-> SomeName).
You were correct to LEFT JOIN the products and products_location tables. However, you used INNER JOIN for the other two tables in the query and I believe that this may be the reason why you are only seeing records which have a relation between product and location. The logic would be that a product which does not have a location also does not have an entry in, for example, the products_attributes table. Hence, the non matching records you want to retain would be filtered off downstream by an INNER JOIN. To remedy this, use LEFT JOIN everywhere:
SELECT products.id,
products.name AS nameProduct,
products.reference AS refProduct,
products_attributesbuy_price AS priceProduct,
products_location.active,
products_location.sell_price,
products_location.stock AS stockProduct,
provider.title AS p_name
FROM products
LEFT JOIN products_location
ON products_location.product_reference = products.reference AND
products_location.active = 1 AND
products_location.location_id = 4
LEFT JOIN products_attributes
ON products_attributes.product_reference = products.reference AND
products.lang = 'es' AND
products_attributes.provider = 6
LEFT JOIN companies AS provider
ON products_attributes.provider = provider.id AND
provider.id = 6
I don't know if a similar question have been asked, but I looked fow more than hour on mysql in stackoverflow
My problem is, i have multiple tables and I need to join them with both left join and inner join in mysql
Entity table :
id (key) | entityName
1 | john
2 | harris
3 | henry
4 | mark
5 | dom
Activity table
id (key) | entityID | status
1 | 1 | 1
2 | 2 | 0
3 | 4 | 1
Geodata table
id (key) | entityID | moment (timestamps when the entry was done)
1 | 1 | 1429542320 (smaller)
2 | 1 | 1429542331 (bigger)
3 | 2 | 1429542320 (smaller)
4 | 2 | 1429542331 (biger)
5 | 4 | 1429542331 (bigger)
Info table
id (key) | entityID | infos | date
1 | 1 | xxx | today
2 | 1 | xxx | yesterday
3 | 2 | xxx | today
4 | 2 | xxx | yesterday
5 | 3 | xxx | yesterday
6 | 5 | xxx | today
7 | 5 | xxx | yesterday
8 | 5 | xxx | tomorrow
So basically, I need every Entities that has an info for today
Moreover, if their status is true (or 1) (from activity table), show me their date in geodata table.
So this is what i've got :
SELECT e.id,
e.entityName,
i.infos,
a.status,
MAX(g.moment) -- but the max only if status =1
FROM entities AS e
LEFT JOIN activity AS a ON a.entityID = e.id
LEFT JOIN geodata AS g ON g.entityID = e.id
INNER JOIN infos AS i ON e.id = i.entityID
WHERE i.date = 'today'
GROUP BY e.id
I want every entities that has an info about today, but some of them have activity too, so i want to show it (if it doesn't just let the left join put NULL) If the status is 0, I don't need the moment, but if its true, I only need the bigger one (its numbers, so Max() should do it but it breaks)
The expected results is :
id (key) | entityName | infos | status | MAX(moment) | ..other columns
1 | john | xxx | 1 | 1429542331 (the bigger one)
2 | harris | xxx | 0 | NULL
5 | dom | xxx | NULL | NULL
If someone can help me, I'll be very thankful :)
PS.: Sorry for my english, it isn't my first language
You could change the
MAX(g.moment)
to
IF(a.status<>1, NULL, MAX(g.moment))
or alternately change LEFT JOIN geodata AS g ON g.entityID = e.id to LEFT JOIN geodata AS g ON a.entityID = e.id AND a.status = 1
Which one is faster will probably depend on your actual data; the second may be faster as less records are joined, but the more complicated join condition it uses might slow down the joining.
I have two tables that I am trying to query, and I can only get about half the information I need. The two tables are:
client_skills_new:
+----+-----------+------------+----------+-------------+
| id | client_id | job_sector | job_type | job_name |
+----+-----------+------------+----------+-------------+
| 79 | 24 | 3 | 39 | Accountant |
+----+-----------+------------+----------+-------------+
| 80 | 25 | 3 | 115 | Broker |
+----+-----------+------------+----------+-------------+
| 81 | 24 | 5 | 241 | Shop Worker |
+----+-----------+------------+----------+-------------+
and
job_sectors:
+-----+--------------------------+---------------+
| id | name | job_sector_id |
+-----+--------------------------+---------------+
| 3 | Accounting & Finance | 0 |
+-----+--------------------------+---------------+
| 115 | Brokerage | 3 |
+-----+--------------------------+---------------+
| 22 | Sales & Retail | 0 |
+-----+--------------------------+---------------+
The job sectors table actually contains job sectors and job types in one column (name). job_sector id links the two (ie brokerage is a subheading of accounting and finance - job_sector_id = id).
In the client_skills_new table the numbers stored under job_sector and job_type relate to the id column of job_sectors. What I am trying to do is write a query which will join the two to give me the textual value in the job_sectors table related to the job_sector and job_type integers in client_skills_new.
So far I have a query as follows:
SELECT client_skills_new.job_sector, job_sectors.id, job_sectors.name
FROM job_sectors
LEFT JOIN client_skills_new
ON client_skills_new.job_sector = job_sectors.id
WHERE client_id='$client_id';
From this, I get results as follows:
+------------+----+--------------------------+
| job_sector | id | name |
+------------+----+--------------------------+
| 3 | 3 | Accounting & Finance |
+------------+----+--------------------------+
| 22 | 22 | Sales & Retail |
+------------+----+--------------------------+
Which given id of 24 from my top table gives me about half of what I need. I'd like the query to also include the text name corresponding to job_type. I'm not quite sure what I need to add to finish the query. I tried a second left join but this kept erroring.
The output I'm looking for, given each id in client_skills_new, is as follows:
+----+--------------------------+-----------+----------+
| id | job_sector | job_type | job_name |
+----+--------------------------+-----------+----------+
| 80 | Accounting & Finance | Brokerage | Broker |
+----+--------------------------+-----------+----------+
Yes, you need 2 LEFT joins but the other way around:
SELECT c.id,
js.name AS job_sector,
jt.name AS job_type,
c.job_name
FROM client_skills_new AS c
LEFT JOIN job_sectors AS js
ON c.job_sector = js.id
LEFT JOIN job_sectors AS jt
ON c.job_type = jt.id
WHERE c.client_id='$client_id' ;
The problem is the where clause. It is "undoing" the left outer join, because the values in one table are NULL when there is no match.
The fix is to move the logic to the on clause:
SELECT client_skills_new.job_sector, job_sectors.id, job_sectors.name
FROM job_sectors LEFT JOIN
client_skills_new
ON client_skills_new.job_sector = job_sectors.id and
client_id='$client_id';
I have one report page which displays summarized data of other report.I have used php and mysqli. Let me explain you in deep.
I have a web application of store, where you can add product details. Using these product details you can generate packaging list report of products. And based on the generated packaging list report I need to generate one other report which contains summarized data of the packaging list.
below are my tables:
product table:
id | name | desc_id | purity | style_no | type | duty
1 | ABC | 1 | 18 | TEST123 | R | 100
2 | XYZ | 2 | 14 | TEST456 | B | 80
3 | DEF | 1 | 14 | TEST122 | R | 80
4 | PQR | 1 | 18 | TEST124 | R | 120
5 | HJK | 3 | 18 | TEST134 | B | 300
Description table:
id | descrip
1 | Gold Diamond Ring
2 | Gold Diamond Pendant
3 | Gold Diamond Earring
packaging_master table
id | name
1 | pkg_1
2 | pkg_2
packging_details table
id | pkg_id | prod_id
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 1 | 4
5 | 1 | 5
I have used below query to generate the packaging list report for specific id, which works correctly.
SELECT id, (SELECT descrip FROM description WHERE id = desc_id ) AS descrip,
style_no, type , purity, duty FROM product WHERE id IN ( SELECT prod_id FROM packaging_list_details WHERE pkg_id =1 ) ORDER BY descrip ASC , purity ASC
which displays below result:
id | descrip | style_no | type | purity | duty
1 |Gold Diamond Ring | TEST123 | R | 18 | 100
4 |Gold Diamond Ring | TEST124 | R | 18 | 120
3 |Gold Diamond Ring | TEST122 | R | 14 | 80
2 |Gold Diamond Pendant| TEST456 | B | 14 | 80
5 |Gold Diamond Earring| TEST134 | B | 18 | 300
Now I want summarized data of above result using query.
Like:
id | descrip | purity | qty | duty
1 |Gold Diamond Ring | 18 | 2 | 220
2 |Gold Diamond Ring | 14 | 1 | 80
3 |Gold Diamond Pendant| 14 | 1 | 80
4 |Gold Diamond Earring| 18 | 1 | 300
How can I achieve this?
You need to use the GROUP_BY statement - See MySql docs for more info.
This will translate the query to such
SELECT d.descrip, p.purity, count(p.purity) as qty, sum(p.duty)
FROM product p
INNER JOIN Description d ON p.desc_id = d.id
LEFT OUTER JOIN packaging_details pg on pg.prod_id = p.id
GROUP BY d.descrip, p.purity
ORDER BY d.descrip desc, p.purity desc
You can also use the sub select methodology you were using, but I prefer using joins. INNER JOIN will link both tables so that all their records are returned. OUTER JOIN will return all rows from the tables on the LEFT of the statement and matches them to values from the tables on the RIGHT.
See a full SQL Fiddle sample.
NOTE: I am not sure where you are getting the values for Id in your sample - Are they simply row numbers?
I think you should rewrite your query using JOINs:
SELECT
P.id
,D.descrip
,P.style_no
,P.type
,P.purity
,P.duty
FROM
packaging_list_details PLD
JOIN
product P ON
(P.id = PLD.prod_id)
LEFT JOIN
description D on
(D.desc_id = P.id)
WHERE
(PLID.pkg_id = 1)
That should give you the same result you already have. To get the totals, you can write a new query, similar to the above:
SELECT
P.id
,D.descrip
,P.type
,P.purity
,COUNT(p.id) as total_products
,SUM(P.duty) as total_duty
FROM
packaging_list_details PLD
JOIN
product P ON
(P.id = PLD.prod_id)
LEFT JOIN
description D on
(D.desc_id = P.id)
WHERE
(PLID.pkg_id = 1)
GROUP BY
P.id
,D.descrip
,P.type
,P.purity
The second query gives you the totals you are looking for.