I'm trying to display businesses along with their highest discount offer. But I still would like to display businesses with no offer.
Businesses are stored in business_tb
business_id | business_name
------------+---------------
1 | aaa
2 | bbb
3 | ccc
offered discounts by those businesses are stored in deal_offer_tb
deal_offer_id | business_id | deal_id
--------------+-------------+----------
1 | 1 | 3
2 | 1 | 2
3 | 2 | 0
4 | 1 | 1
5 | 3 | 3
and types of discounts are stored in deal_tb.
deal_id | discount
--------+----------
1 | 40%
2 | 30%
3 | 20%
4 | 10%
So the display I wanted should look something like this:
1 | aaa | 40%
2 | bbb | ---
3 | ccc | 20%
But with my current query:
SELECT a.business_id, a.business_name, c.discount
FROM business_tb a
LEFT JOIN (SELECT min(deal_id) AS deal_id, business_id FROM deal_offer_tb GROUP BY business_id) b ON a.business_id = b.business_id
LEFT JOIN deal_tb c ON b.deal_id = c.deal_id
I only get:
1 | aaa | 40%
3 | ccc | 20%
It does not display businesses with no offered discounts.
How am I suppose to get my desired output?
UPDATE: I don't know what happened earlier, but my query is working the way I wanted it. Thanks to the effort of those who answered. Appreciate it, big time!
I would approach this by using a subquery to find the greatest discount for each business, joining the deal_offer_tb and deal_tb tables. Then, join this subquery to the business_tb table to get the final result. Note that I use an initial LEFT JOIN to account for that a given business may not even have an deals associated with it. In that case, I assign a maximum discount of 0 to that business (which makes sense, since then the full regular price would apply).
SELECT
t1.business_id,
t1.business_name,
COALESECE(t2.max_discount, 0) AS max_discount
FROM business_tb t1
LEFT JOIN
(
SELECT t1.business_id, MAX(t2.discount) AS max_discount
FROM deal_offer_tb t1
INNER JOIN deal_tb t2
ON t1.deal_id = t2.deal_id
GROUP BY t1.business_id
) t2
ON t1.business_id = t2.business_id
This query is essentially your query (with table aliases):
SELECT b.business_id, b.business_name, d.discount
FROM business_tb b LEFT JOIN
(SELECT MIN(deal_id) AS deal_id, business_id
FROM deal_offer_tb dot
GROUP BY business_id
) dot
ON b.business_id = dot.business_id LEFT JOIN
deal_tb d
ON d.deal_id = dot.deal_id;
By the definition of LEFT JOIN, it will keep all rows in business_tb, regardless of whether or not there are matches in the rest of the FROM clause. You have no additional filtering (via WHERE) or aggregation. Hence, this should returns all the rows in business_tb.
Below is one way to do the query:
SELECT
a.business_id, a.business_name, b.max
FROM business_tb a
INNER JOIN (
SELECT
c.business_id, MAX(d.discount) AS max
FROM deal_offer_tb c
LEFT JOIN deal_tb d ON c.deal_id = d.deal_id
GROUP BY c.business_id
) b ON a.business_id = b.business_id;
You don't have deal_id 0 in deal_tb, so I assume it's null for deal_offer_id 3.
Related
I have 3 tables
admin_courses
Admin_course_groups
Group_permision
admin_courses
c_id | c_name | c_status
1 | test1 | 1
2 |test2 |1
3 |test3 |1
4 test4 1
Admin_course_groups
a_id | fk_c_id |fk_g_id |start_date |end_date
1 | 1 | 1 | 2018-10-10 |2018-10-20
2 | 5 |1 | 2018-10-10 | 2018-10-20
3 | 4 |3 |2018-10-10 |2018-10-20
Group_permision
gp_id|fk_g_id|user_id
1 1 2
2 3 2
2 1 3
Here total four courses added i want to know how many course assign to each user, i have query
SELECT c_id
, c_name
, COUNT(a_id) AS nam
, MIN(start_date) as start_date
, MIN(end_date) as end_date
FROM admin_courses c
LEFT
JOIN Admin_course_groups g
ON g.fk_c_id = c.c_id
left
join Group_permision h
on g. fk_g_id=h.fk_g_id
and users_id=3
where c.c_status=1
GROUP
BY c_id
So here it will return all course, if course is assigned for user COUNT(a_id) will 1 else it 0.
Now my issue is that if users_id is 3 user assigned only 1 course but i got 3 instead of 1.
Please help me. any help would be appreciated.
You are counting wrong field. To count number of Users in a Course, you need to count user_id; Also, use Count(Distinct ...) to avoid counting a same user multiple times.
Also, note that I have added c.c_name to Group By clause, to be compatible with only_full_group_by mode. Do Read: SELECT list is not in GROUP BY clause and contains nonaggregated column .... incompatible with sql_mode=only_full_group_by
You dont need to join on user_id, to count total number of users. It restricts your data.
Try:
SELECT c.c_id
, c.c_name
, COUNT(DISTINCT h.user_id) AS nam
, MIN(g.start_date) AS start_date
, MIN(g.end_date) AS end_date
FROM admin_courses AS c
LEFT
JOIN Admin_course_groups AS g
ON g.fk_c_id = c.c_id
LEFT
JOIN Group_permision AS h
on g.fk_g_id = h.fk_g_id
WHERE c.c_status=1
GROUP
BY c.c_id,
c.c_name
Your question is missing some crucial information, but if I understood the problem correctly, I would simply try to add Distinct to the count :
SELECT `c_id`, `c_name`, COUNT(distinct `a_id`)
....
I have three tables:
person_table
id| name | gender
1 | Joe | male
2 | Jane |female
3 | Janet | female
4| Jay | male
etc...
product_table
id| name
1 | magazine
2 | book
3 |paper
4 | novel
etc...
**person_product
person_id| product_id | quantity
1 | 1 | 1
1 | 3 | 3
2 | 3 | 1
4 | 4 | 2
etc...
I have tried to make a query that will return a table like this:
person_id| person_name | product_name| quantity
but i can't make it so that if lets say John has no books, it should display
(johns id) John|book|0
instead of just skipping this line.
Where did i go wrong?
here is what i managed to come up with:
SELECT p.*, f.name, l.quantity
FROM person_product AS l
INNER JOIN people_table AS p ON l.person_id=p.id
INNER JOIN product_table AS f ON l.product_id=f.id
ORDER BY id`
It seems that you're generating a report of all people, against all products with the relevant quantity; on a large data set this could take a while as you're not specifically joining product to person for anything other than quantity:
SELECT
p.id,
p.name,
p.gender,
f.name,
IFNULL(l.quantity,0) AS quantity
FROM person_table AS p
JOIN product_table AS f
LEFT JOIN person_product AS l
ON l.person_id = p.id
AND l.product_id = f.id
ORDER BY p.id, f.name
Which results in:
Is that more-or-less what you're after?
you need to start with people_table than using left join you need to bring other table data.
as you need 0 value if null than you can use function IFNULL
SELECT p.*, f.name, IFNULL(l.quantity,0)
FROM people_table AS p
LEFT JOIN person_product AS l ON l.person_id=p.id
LEFT JOIN product_table AS f ON l.product_id=f.id
ORDER BY p.id
if has no book shouldn't appear in the table , try this (easy to understand) :
SELECT NAME
,'0'
,'0'
FROM person_table
WHERE id NOT IN (
SELECT person_id
FROM person_product
)
UNION
SELECT person_id
,product_id
,quantity
FROM person_product;
Im not very familiar with using 'join' in queries. I really tried solving this by my own, but it seems to be too hard.
I got 2 Tables:
Table 'users':
+-----------------+-----------------+
| member | online |
+-----------------+-----------------+
| mahran | 1 |
| peter | 1 |
| Jen | 1 |
| Steve | 0 |
+-----------------+-----------------+
Table 'tickets'
+-----------------+----------------+----------------+
| name | category | time |
+-----------------+----------------+----------------+
| mahran | silver | 1 |
| peter | blue | 1 |
| mahran | blue | 2 |
| peter | red | 3 |
| peter | green | 2 |
| Jen | silver | 1 |
+-----------------+----------------+----------------+
The chellange:
I need each member (users.member) who's online (users.online). The next thing is to get the category for each member (user.member = tickets.name) with the highest time (probably ORDER BY time DESC LIMIT 1).
So, for example:
Peter is online. Peters highest time is 3 at the position of category=red. So I want peter to show up in the result with his category 'red'. Mahran would show up with blue. Jen would get silver. And steve would be left out because he's not online.
I hope this was clear. In general I know how the queries would look like but theres no chance for me merging them together.
What needs to be merged:
SELECT member FROM users WHERE online = 1;
|
v for each member
SELECT category FROM tickets WHERE name=users.member ORDER BY time DESC.
So, any ideas how to solve this?
Here is a fiddle with a not working query: Click
You can do this easily with a correlated subquery:
select u.member,
(select t.category
from tickets t
where t.name = u.member
order by t.time desc
limit 1
) as MostRecentCategory
from users u
where u.online = 1;
This can make use of the following indexes: users(online, member) and ticket(member, time, category).
Here is the query you're looking for:
SELECT U.member
,T.category
FROM users U
INNER JOIN tickets T ON T.name = U.member
INNER JOIN (SELECT T2.name
,MAX(T2.time) AS [maxTime]
FROM tickets T2
GROUP BY T2.name) AS M ON M.name = T.name
AND M.maxTime = T.time
WHERE U.online = 1
The use of [name] to join the two tables is not a good practice, it's much better to use keys instead. But my query is just here to help you understanding the process of jointure.
Hope this will help you.
If i understand you correctly
SELECT DISTINCT users.member, tickets.category FROM tickets JOIN users ON users.member = tickets.name WHERE users.online = 1 ORDER BY tickets.time DESC
Can you make sql fiddle?
USE DISTINCT
stackoverflow.com/questions/11704012/mysql-distinct-join
try this
SELECT DISTINCT User.member,Ticket.category FROM users AS USER
INNER JOIN tickets AS Ticket ON (User.member = Ticket.name)
WHERE User.online = 1;
Sorry, but peter seems to be RED, It's time is 3. Don't you?
Depending on table definition, is not guaranteed to have one only result for each user.
For example, if peter has time 3 in two categories, you can get one different category depending of the SQL sorting method.
To be sure, tickets.Category and tickets.time must be in a unique key (both toghether, not a unike key for each field)
Assuming that, the Query could be this.
select t2.name, t2.category
from
tickets t2
INNER JOIN (Select
u.member, max(time)
from users u, tickets t
where
u.member = t.name
and u.online = 1
group by u.member
) as usermaxtime on t2.name = usermaxtime.member;
I'm making a search function in PHP and I have three tables that I wish to join to a single one; the three tables looks as follow:
band
ID | bands
---+----------
1 | Muse
2 | Coldplay
3 | etc.
release
ID | releases
---+----------
1 | Showbiz
2 | Origin of Symmentry
3 | etc.
track
ID | tracks
---+-----------
1 | Sunburn
2 | Muscle Museum
3 | etc.
I want these tables to be put into this:
discografic
ID | band_id | release_id | track_id
---+----------+-------------+---------
1 | 1 | 1 | 1
2 | 1 | 1 | 2
3 | etc.
So that the table with the SQL code looks like this:
discografic
ID | bands | releases | tracks
---+----------+-------------+---------
1 | Muse | Showbiz | Sunburn
2 | Muse | Showbiz | Muscle Museum
3 | etc.
I want to INNER JOIN these tables. I joined one but I can't really figure out how the get the last joined as well.
SELECT *
FROM band
INNER JOIN discografic
ON band.id = discografic.band_id
This should probably have its own question; I also want to be able to search this database, but only have the result show up once, and also reference to the band every time. For example, if I search "Showbiz" it will give me "Muse", and only show it once.
Note: This is for testing purposes only, security is none of my concerns.
Try with this query:
select d.id,b.bands,r.releases,t.tracks from discografic as d INNER JOIN band as b on
d.band_id=b.id INNER JOIN release as r on d.release_id=r.id INNER JOIN track as t on
d.track_id=t.id GROUP BY d.id
Try This query
Select a.ID,b.bands,c.releases,d.tracks from discografic as a
inner join band as b on a.band_id = b.ID
inner join release as c on a.release_id = c.ID
inner join track as d on a.track_id = d.ID
where b.bands = 'Muse'
Use this query to insert the data like you wanted:
Insert into discograpy
(id,bands,releases,tracks)
SELECT band.ID,bands,releases,tracks
FROM band
INNER JOIN releases
ON band.id = releases.id
inner join track
on band.id = track.id
Use this query to show you only one band:
Declare #releases varchar(50)
Set #releases = 'showbiz'
SElect distinct bands from discograpy where releases = #releases
Here any variable can be passed or set in place of showbiz. This is an example
I need to generate some big data from many tables, regarding filters, at there also i need to get the sum of some columns, and also counts of rows like example
i have 5 records
ID | NAME | DELETED
1 | A | 1
2 | A | 0
3 | A | 1
4 | B | 1
5 | C | 1
I have the query,
SELECT p.name, sum(p.deleted) as del, count(p.id) as numbers from products as p
join other AS b ON p.id=b.id
The output i need is,
The sum of deleted records
NAME | Deletion | Count
A | 2 | 3
B | 1 | 1
C | 1 | 1
Try this ::
SELECT
p.name,
sum(p.deleted) as del,
count(id) as numbers
from products as p
join other AS b ON p.id=b.id
group by p.name
You should not need to join to get your result. This should work:
SELECT name, sum(deleted), count(1)
FROM products
GROUP BY name
SELECT name,
SUM(CASE WHEN deleted = 1 THEN 1 ELSE 0 END) Deletion,
COUNT(*) `COunt`
FROM products
GROUP BY name
OR
SELECT name,
SUM(deleted) Deletion,
COUNT(*) `COunt`
FROM products
GROUP BY name;
SQLFiddle Demo (both queries)