I need a little help here
It is very simple problem but I don't know why I can't get what I want
Database
store
id | value
5 | s
favorite
id | store_id | value
1 | 5 | f
2 | 5 | f
3 | 5 | f
party
id |store_id | value
1 | 5 | p
2 | 5 | p
my query :
SELECT COUNT(p.`id`) AS parties, COUNT(f.`id`) AS favorites,s.* FROM store s
LEFT JOIN party p ON p.`store_id` = s.`id`
LEFT JOIN favorite f ON f.`store_id` = s.`id`
GROUP BY s.`id`
result
parties | favorites | id | value
6 | 6 | 5 | s
this is the result I want
parties | favorites | id | value
2 | 3 | 5 | s
Can anyone help me?, I already tried all approach I can think of
You need to count DISTINCT id's if you want a separate count of parties/favorites per store, that will eliminate the duplicates you're getting due to the JOIN;
SELECT COUNT(DISTINCT p.`id`) AS parties,
COUNT(DISTINCT f.`id`) AS favorites,
s.*
FROM store s
LEFT JOIN party p ON p.`store_id` = s.`id`
LEFT JOIN favorite f ON f.`store_id` = s.`id`
GROUP BY s.`id`;
Related
I have 3 tables. clients, sales and potential_sales.
The basic structure is as follows:
Clients Table:
+-----------+-------+----------------+
| client_id | name | address |
+-----------+-------+----------------+
| 1 | john | 12 blue ave |
| 2 | paul | 34 green lane |
| 3 | peter | 69 yellow road |
+-----------+-------+----------------+
Potential Sales Table:
+----------+------------+---------------------+
|product_id | client_id | received_free_promo |
+-----------+------------+---------------------+
| 3 | 1 | 1 |
| 4 | 2 | 0 |
| 5 | 2 | 1 |
+-----------+------------+---------------------+
Sales:
+----------+-----------+-----------+
| sales_id | client_id | product_id |
+----------+-----------+------------+
| 1 | 2 | 4 |
| 2 | 43 | 4 |
| 3 | 2 | 5 |
| 4 | 18 | 93 |
+----------+-----------+------------+
I want to join clients and potential_sales tables ONLY IF
1) received_promo equals 1 AND
2) they actually bought the promo package (i.e. the product_id for the potential sale has an entry into the sales table ). If they didn't eventually buy the free_promo product then I do not want to join the clients and potential_sales table at all. This is important - I can't simply JOIN to figure it out because this is only a small part of a bigger query and I can't afford to JOIN for no reason.
(Here is how I would like it to work. It's mainly pseudo-code to describe what I want to happen)
SELECT
c.*
FROM
clients c
LEFT JOIN potential_sales ps ON ps.client_id=c.id
LEFT JOIN sales ps ON s.product_id=ps.product_id
IF(s.sales_id) JOIN potential_sales ps ON ps.client_id=c.id
How do I do this in MySQL? I haven't come close to a solution. Please help!
Try this:
SELECT A.*, B.product_id, B.received_free_promo
FROM Clients A JOIN
(SELECT * FROM PotentialSales
WHERE received_free_promo=1) B
ON A.client_id=B.client_id
WHERE EXISTS (SELECT 1 FROM Sales C
WHERE A.client_id=C.client_id
AND B.product_id=C.product_id);
See Demo on SQL Fiddle.
What you are missing is the EXISTS clause:
SELECT
C.*,
P.*
FROM
Clients AS C
INNER JOIN PotentialSales AS P ON C.client_id = P.client_id
WHERE
P.received_free_promo = 1 AND
EXISTS (
SELECT
'the client already sold that product'
FROM
Sales AS S
WHERE
S.client_id = C.client_id AND
S.product_id = P.product_id)
Try this..." select * from client as c natural join potential as p join sales as s on p.product_id = s.product_id where received_promo = 1". select * will mention everything from all the 3 tables. You can choose what you want as the result.
I'm running MySQL 5.1.71. In my database there are three tables - load, brass and mfg with load being my "main" table. My goal is to query load and have mfg.name included in the results. I've tried various iterations of JOIN clauses vs sub-queries both with and without WHERE clauses. It seems this should be pretty trivial so I'm not sure how I can't arrive at the solution.
load
-------------------------
| id | desc | brass_id |
-------------------------
| 1 | One | 2 |
| 2 | Two | 1 |
-------------------------
brass
---------------
| id | mfg_id |
---------------
| 1 | 6 |
| 2 | 8 |
---------------
brass_mfg
------------------------
| id | name |
------------------------
| 6 | This Company |
| 8 | That Company |
------------------------
My desired results would be...
results
---------------------------
| load | mfg |
---------------------------
| One | That Company |
| Two | This Company |
---------------------------
A load ID will always have only a single brass ID
A brass ID will always have only a single mfg ID
EDIT
The previously provided sample data (above) has been updated. Also, below are the query I'm running and the results I'm getting. The company is wrong in each record that is returned. I've included in the query and the results the IDs across the tables. The company names that appear are not the names in for the IDs in the mfg table.
SELECT
load.id AS "load.id",
load.brass_id AS "load.brass_id",
brass.id AS "brass.id",
brass.mfg_id AS "brass.mfg_id",
brass_mfg.id AS "brass_mfg.id",
brass_mfg.name AS "brass_mfg.name"
FROM `load`
LEFT JOIN brass ON load.brass_id = brass.id
LEFT JOIN brass_mfg ON brass.id = brass_mfg.id
-----------------------------------------------------------------------------------------
| load.id | load.brass_id | brass.id | brass.mfg_id | brass_mfg.id | brass_mfg.name |
-----------------------------------------------------------------------------------------
| 1 | 2 | 2 | 6 | 2 | Wrong Company |
| 2 | 1 | 1 | 8 | 1 | Incorrect Company |
-----------------------------------------------------------------------------------------
Look at your tables and see what data relates to one another then build up joins table by table to get your desired output.
SELECT p.desc AS Product, m.name AS mfg
FROM product p
INNER JOIN lot l ON p.lot_id = l.id
INNER JOIN mfg m ON l.mfg_id = m.id
If this is single - single relationship, why having middle table?
In your case the best scenario is simple join.
SELECT pt.desc as Product, mfg.name as Mfs
FROM Product pt
Join Lot lt on lt.id = pt.lot_id
Join Mfg mf on mf.id = lt.mfg_id
You have an error in your join query.
Try this one:
Select
l.id AS "load.id",
l.brass_id AS "load.brass_id",
b.id AS "brass.id",
b.mfg_id AS "brass.mfg_id",
m.id AS "brass_mfg.id",
m.`name` AS "brass_mfg.name"
FROM `load` as l
LEFT JOIN brass as b ON l.brass_id = b.id
LEFT JOIN brass_mfg as m ON b.mfg_id = m.id
You need LEFT JOIN only
I'm a little bit confused about which join to apply and where.
I have a mysql database that does betting in an IRC client.
It stores usernames , their guess and the eventual outcome of the game they bet on
the outcomes_table is like this
+--------------+
| id outcome |
+--------------+
| 1 win |
| 2 lose |
+--------------+
the user_table is like this
+----+----------+----------+-------------------+
| id | username | guess_id | bettingsession_id |
+----+----------+----------+-------------------+
| 1 | name1 | 1 | 1 |
| 2 | name2 | 1 | 2 |
| 3 | name3 | 2 | 2 |
4 name1 1 2
+----+----------+----------+-------------------+
the betting_session_table is like this:
+----+---------+
| id | result |
+----+---------+
| 1 | 1 |
| 2 | 2 |
+----+---------+
I want to get a list of the bets of a user with their guess joined to the outcome and the result joined to the
eg:
select each row a different bet username, guess (win/lose), result (win/lose)
Something like:
SELECT *
FROM user_table
INNER JOIN betting_session_table ON bettingsession_id = betting_session_table.id
INNER JOIN outcomes_table ON guess_id = outcomes_table.id
INNER JOIN outcomes_table ON result = outcomes_table.id
WHERE username = 'name1'
However this doesn't work, not sure but I don't think it lets me join the outcomes_table.id twice to two different columns but I want to this because the user may bet 'win' but result 'lose' etc.
EG: I want to return
+----+----------+----------+----+---------+--------------------+----+--------+----+---------+
| id | username | guess_id | id | outcome | betting_session_id | id | result | id | outcome |
+----+----------+----------+----+---------+--------------------+----+--------+----+---------+
| 1 | name1 | 1 | 1 | win | 1 | 1 | 1 | 1 | win |
| 4 | name1 | 1 | 1 | win | 2 | 2 | 2 | 2 | lose |
+----+----------+----------+----+---------+--------------------+----+--------+----+---------+
EDIT:
In the end I used two separate alias for each join which seems to work; here is the code from the actual table that works rather than the cut down example above.
SELECT *
FROM `xcoins_betting_log` A
LEFT JOIN `xcoins_betting_session` B ON A.betting_session_id = B.id
LEFT JOIN `xcoins_common_tables`.`xcoins_betting_outcomes` C ON A.guess_id = C.id
LEFT JOIN `xcoins_common_tables`.`xcoins_betting_outcomes` D ON B.outcome_id = D.id
WHERE `user_id` =9
I'm not sure if this is what you want, but I hope so.
SELECT
usr.*,
res.outcome,
IF(res.id = usr.guess_id, 'User win', 'User lose') AS result
FROM user_table AS usr
INNER JOIN betting_session_table AS bet ON
bet.id = usr.bettingsession_id
INNER JOIN outcomes_table AS res ON
res.id = bet.result
WHERE usr.username = 'name1'
Choose correct join
The most common joins is LEFT and INNER. Lets say the users have placed their bets, but the football game (or whatever) isn't completed yet, then you won't have the row in the outcomes_table right? The game isn't finished so the results will come later.
If you use INNER JOIN, the row in the outcomes_table won't match for unfinished games --- INNER JOIN requires matches.
If you want to see the bets also before the game has started, you can use LEFT JOIN. LEFT JOIN won't remove rows that hasn't got any outcome, the users will still be listed --- LEFT JOIN doesn't care.
INNER JOIN: Game must have result
LEFT JOIN: Game might have result
Users
+--------+--------------+----------+--------------+
| userID | userUsername | userName | userLastName |
+--------+--------------+----------+--------------+
| 6 | richard | Ricardo | Vega |
| 10 | jason | Jason | Bourne |
+--------+--------------+----------+--------------+
Restocks
+-----------+-------------+--------+--------+-----------------+
| restockID | restockDate | itemID | userID | restockQuantity |
+-----------+-------------+--------+--------+-----------------+
| 1 | 2012-02-29 | 1 | 6 | 48 |
| 2 | 2012-02-29 | 1 | 10 | 100 |
| 3 | 2012-02-29 | 2 | 10 | 50 |
| 4 | 2012-02-29 | 2 | 6 | 100 |
| 5 | 2012-02-29 | 2 | 6 | 200 |
| 6 | 2012-02-29 | 2 | 10 | 2000 |
| 7 | 2012-02-29 | 1 | 10 | 2000 |
+-----------+-------------+--------+--------+-----------------+
Items
+--------+--------------------+
| itemID | itemName |
+--------+--------------------+
| 1 | Coca Cola (lata) |
| 2 | Cerveza Sol (lata) |
+--------+--------------------+
Ok guys, i have supplied some sample data as requested. I need to get this table:
+--------+--------------------+---------------+-------------+----------+--------------+--------------+
| itemID | itemName | itemExistence | restockDate | userName | userLastName | userUsername |
+--------+--------------------+---------------+-------------+----------+--------------+--------------+
| 2 | Cerveza Sol (lata) | 2350 | 2012-02-29 | Jason | Bourne | jason |
| 1 | Coca Cola (lata) | 2148 | 2012-02-29 | Ricardo | Vega | richard |
+--------+--------------------+---------------+-------------+----------+--------------+--------------+
But, i need restockDate to be THE LATEST ONE for each itemName. In the example, it shows the first restock and not the latest one. I just need to show what's the existence for the item and when was restocked for last time, not first time.
If my tables are not good or so, please suggest a new schema.
I know maybe this is a lot so i will tip 5 USD (Paypal) to the one how can help me with this. Promise.
As discussed in comments, many restocks can be performed on the same day so it is not possible to compare dates in this case. Two options are presented here: Use the incremental PK from restocks table or restructure the table. For the first case, this is the solution:
select i.itemID, i.itemName, i.itemExistence, r.restockDate, u.userName,
u.userLastName, u.userUsername
from items i
left join (
select r1.restockDate, r1.itemID, r1.userID from restocks r1
left join restocks r2
on r1.itemId = r2.itemId and r1.restockId < r2.restockId
where r2.restockDate is null
) as r on i.itemID = r.itemID
inner join users u on r.userID = u.userID
For the second case, the restructre would imply changing the date field to a unique datetime that would uniquely identify a record. That is the best solution, however, it does require to also update any previous data present in the table. That means, to update all the records that have the same date for a single product restock and set different date times to them.
The lazy one (like me), would go for the first option :) Let me know if you have any doubt about this.
first get the distinct from items table and then use it to join others
SELECT items.*, restocks.restockDate, users.userName, users.userLastName, users.userUsername
FROM (SELECT DISTINCT items.itemID, items.itemName, items.itemExistence FROM items) AS items
LEFT JOIN restocks on items.itemID = restocks.itemID
LEFT JOIN users on restocks.userID = users.userID
GROUP BY items.itemName
Not Tested
UPDATED
select items.itemID, items.itemName, items.itemExistence, restocks.restockDate, users.userName, users.userLastName, users.userUsername
from items
inner join restocks on items.itemID = restocks.itemID
inner join users on restocks.userID = users.userID
GROUP BY items.itemName
select
items.itemID, items.itemName, items.itemExistence,
(select A.restockDate from restocks A where A.itemId = items.itemID limit 0, 1),
(select B.userID from restocks B where B.itemId = items.itemID limit 0, 1),
users.userName, users.userLastName, users.userUsername
from items
left join users on B.userID = users.userID
Please try this.
You don't mention what itemExistence is, so I'm hoping it's a column in the Items table.
Here's an easy way to do it with a self-join:
SELECT i.itemID, i.itemName, i.itemExistence, r1.restockDate,
u.userName, u.userLastName, u.userUsername
FROM Items i
JOIN Restocks r1
ON r1.itemID = i.itemID
JOIN Users u
ON u.userID = r1.userID
LEFT JOIN Restocks r2
ON r2.itemID = i.itemID
AND r2.restockDate > r1.restockDate
WHERE r2.itemID IS NULL
The LEFT JOIN with the WHERE clause ensures that we only pull the row with the latest restockDate.
The advantage of this approach is that it avoids subqueries, which often negate the use of indexes.
You can get duplicate records for a particular item if it was restocked more than once on the same date.
Suppose I have a cooking show:
cookingepisodes
id | date
---------------
1 | A
2 | B
3 | C
4 | D
…
This show reviews products in these categories (left) and are linked by the table to the right:
tests testitems
id | name id | episodeid | testid | name
------------ ------------------------------------
1 | cutlery 1 | 1 | 1 | Forks
2 | spices 2 | 2 | 1 | Knives
3 | 4 | 1 | Spoons
4 | 4 | 2 | Oregano
My desired output is this:
showid | testid | testname
4 | 1,2 | cutlery, spices
3 | NULL | NULL
2 | 1 | cutlery
1 | 1 | cutlery
I've tried using this query, and it works as long as I don't need to concatenate the results (when there are two tests on the same episode). Then the join will create multiple rows based on the number of
SELECT DISTINCT e.*, i.testid, t.name AS testname
FROM cookingepisodes AS e
LEFT OUTER JOIN testitems AS i ON i.episodeid = e.id
LEFT OUTER JOIN tests AS t ON i.testid = t.id
ORDER BY e.date DESC
I've also tried something like this, but I can't get it to work because of the outer block reference (e.id):
JOIN (
SELECT GROUP_CONCAT(DISTINCT testid)
FROM testitems
WHERE testitems.episodeid = e.id
) AS i
Any tips on how I can solve this without restructuring the database?
Try this one -
SELECT
ce.id showid,
GROUP_CONCAT(te.testid) testid,
GROUP_CONCAT(t.name) testname
FROM cookingepisodes ce
LEFT JOIN testitems te
ON te.episodeid = ce.id
LEFT JOIN tests t
ON t.id = te.testid
GROUP BY
ce.id DESC;