mysqli query Order by priority based on 4 different tables - mysql

table_store
store_id title slug
1 Jabong jabong
2 Amazon amazon
table_coupon
coupon_id title store_id
1 Now 50% Off 1
2 New 2020 Sale 2
table_tag
tag_id title priority
1 Latest 5
2 Trending 4
3 Hot 3
table_tag_bind
id tag_id main_id(is coupon_id)
1 1 1
2 1 2
3 2 1
How can i list the products related to store based on tag priority. But dont repeat the same product if it has more than 1 tag. higher the number more tha priority:
my query: please what is wrong in this query?
SELECT DISTINCT(t1.`coupon_id`), t1.`title`
FROM `coupon` AS t1
LEFT JOIN `tag_bind` AS t2 ON t1.coupon_id = t2.main_id
LEFT JOIN `tag` AS t3 ON t3.id = t2.tag_id
WHERE t1.`store_id`='1'
ORDER BY t3.`priority` DESC

You want to order rows in coupons based on their maximum priority in table tag. I would suggest using a correlated subquery for ordering; this seems to me like the simplest way to phrase your requirement:
select c.coupon_id, c.title
from coupon as c
where c.store_id = 1
order by (
select max(t.priority)
from tag_bind tg
inner join tag t on t.id = tg.tag_id
where tg.main_id = c.coupon_id
) desc

Related

Mysql Group by counting issue

Database structure
Table 'applicants'
id org_id team_id
1 1 1
Table 'teams'
id name
1 Test
Table 'teams_members'
id team_id user_id
1 1 1
2 1 2
Table 'users_playeraccounts'
id user_id summoner_id rank_solo
1 1 1 5
2 1 2 8
3 2 3 7
select sum(rank_solo) as rank_sum,
max(rank_solo) as highest_rank,
count(tt.id) as members,
t.name,
o.team_id
from applicants o
join teams t on o.team_id = t.id
join teams_members tt on t.id = tt.team_id
join users_playeraccounts p on tt.user_id = p.user_id
where org_id = :org
group by team_id
This offcourse gives me a result like
rank_sum highest_rank members name team_id
20 8 3 Test 1
Is there a way for me to get both the count of members with their playeraccounts aka
If 1 user has 2 it'll be 2
And also a way for me to keep it as 1 so it literally just counts the rows found in teams_members neglecting the entries in users_playeraccounts?
I want to receive both 2 and 3 as a result of my query.
You want to count the distinct number of entries in tt.id, so you can do that like this:
SELECT ... COUNT(DISTINCT tt.id) AS distinct_members ...
Rather than giving you a count of every row that has a non-null tt.id, you'll get a count of the number of unique values.

How to get the last record using group by

My Query :-
SELECT
p.*,
b.brand_name
FROM
portfolio p,
branding_category b
WHERE
p.category = 'BRANDING'
AND
p.brand_category = b.id
AND
is_active = '1'
GROUP BY
p.brand_category
ORDER BY p.id DESC
LIMIT 10
Suppose portfolio table has :-
id category brand_category is_active title
1 test 8 1 abc
2 test 7 1 pqr
3 test 8 1 xyz
4 test 7 1 ijk
And I want to show Output has :- That is, the last record in each group should be returned.
id category brand_name is_active title
3 test Catalogs 1 xyz
4 test Posters 1 ijk
Edit :-
branding_category
id brand_name
8 Catalogs
7 Posters
i.e, Last row for each group. Please help me on this. I know it is there in stackoverflow Retrieving the last record in each group but I am not able to write for two table.
Try this :-
SELECT p.*,b.brand_name
FROM portfolio p
INNER JOIN branding_category b ON p.brand_category = b.id
INNER JOIN (
SELECT MAX(id) MaxMsgIDForThread
FROM portfolio
WHERE is_active = '1'
GROUP BY brand_category
) g ON p.id = g.MaxMsgIDForThread
Order by p.id Desc
LIMIT 10
Try this,
select x.id,x.category,x.brand_name,x.is_active,x.title from (
select
p.id,p.category,pc.brand_name,p.is_active,p.title,
ROW_NUMBER()over ( ORDER BY p.id) as Rnk
from portfolio p inner join branding_category pc
on p.brand_category=pc.id
) x where Rnk >2

MySQL query limit per join

I tried asking question before, but it's hard to ask in specific without right terminology I am not quite familiar with. So here is an example
Take this query for example:
(
SELECT *
FROM comments
WHERE depth = 0
ORDER BY id DESC
LIMIT 2
)
UNION ALL
(
SELECT c.*
FROM comments c JOIN
(
SELECT id
FROM comments
WHERE depth = 0
ORDER BY id DESC
LIMIT 2
) p ON c.parent_id = p.id
LIMIT 5
)
id parent_id depth title
1 0 0 Title 1
2 0 0 Title 2
3 1 1 Title 3
4 1 1 Title 4
5 1 1 Title 5
6 1 1 Title 6
7 1 1 Title 7
I get two depth 0 rows and in join I get 5 child elements of those two returned queries as well. What I would like to get is to get 5 child elements of each of those two queries, total of 10 rows (of depth 1). For example:
id parent_id depth title
1 0 0 Title 1
2 0 0 Title 2
3 1 1 Title 3
4 1 1 Title 4
5 1 1 Title 5
6 1 1 Title 6
7 1 1 Title 7
8 2 1 Title 8
9 2 1 Title 9
10 2 1 Title 10
11 2 1 Title 11
12 2 1 Title 12
Is that even possible with adjacency list and a requirement to return everything as union (flat)?
edit:
Thanks to Bill Karwin's answer, I got it working now. I wonder still if there is a shorter way to write this. I have 6 (0-5) depth levels, so my query is rather long (and probably not optimal). Here is what it looks like for three levels (you can imagine what the full one looks like).
-- DEPTH LEVEL 0
(
SELECT * FROM (
SELECT *, 1 as _rn, #parent:=0
FROM comments
WHERE depth = 0
ORDER BY id DESC
LIMIT 2
) as D0
)
union all
-- DEPTH LEVEL 1
(
SELECT *
FROM (
SELECT c.*, #row:=IF(#parent=c.comment_id,#row+1,1) AS _rn, #parent:=c.comment_id
FROM (SELECT #parent:=null) AS _init
STRAIGHT_JOIN comments c
INNER JOIN
(
SELECT id
FROM comments
WHERE depth = 0
ORDER BY id DESC
LIMIT 2
) p ON c.comment_id = p.id
) AS _ranked
WHERE _ranked._rn <= 5
)
union all
-- DEPTH LEVEL 2
(
SELECT *
FROM (
SELECT c.*, #row:=IF(#parent=c.comment_id,#row+1,1) AS _rn, #parent:=c.comment_id
FROM (SELECT #parent:=null) AS _init
STRAIGHT_JOIN comments c
INNER JOIN
(
(
SELECT *
FROM (
SELECT c.*, #row:=IF(#parent=c.comment_id,#row+1,1) AS _rn, #parent:=c.comment_id
FROM (SELECT #parent:=null) AS _init
STRAIGHT_JOIN comments c
INNER JOIN
(
SELECT id
FROM comments
WHERE depth = 0
ORDER BY id DESC
LIMIT 2
) p ON c.comment_id = p.id
) AS _ranked
WHERE _ranked._rn <= 2
)
) p ON c.comment_id = p.id
) AS _ranked
WHERE _ranked._rn <= 2
)
You can't do this with LIMIT, because LIMIT is applied after the result set is completely finished, after all joining, grouping, sorting, etc.
You're using a variation of the greatest-n-per-group type of query. It's tricky to do this in MySQL because MySQL doesn't support the ROW_NUMBER() window function supported by many other SQL databases.
Here's a workaround for MySQL, in which user-defined variables can take the place of partitioned row numbers:
SELECT *
FROM (
SELECT c.*, #row:=IF(#parent=c.parent_id,#row+1,1) AS _rn, #parent:=c.parent_id
FROM (SELECT #parent:=null) AS _init
STRAIGHT_JOIN comments c
INNER JOIN
(
SELECT id
FROM comments
WHERE depth = 0
ORDER BY id DESC
LIMIT 2
) p ON c.parent_id = p.id
) AS _ranked
WHERE _ranked._rn <= 5

Select ONLY one row per category

Ok I have siple table which contains data:
id cat_id title (with random values)
1 1 test
2 1 tstt
3 3 tewt
4 2 4324
5 3 rterter
Now, I need to create a query which selects only ONE raw per category (cat_id)
(possibly with lowest ID and ordered by cat_id)
So the result should be:
1 1 test
4 2 4324
3 3 tewt
Use GROUP BY :
SELECT MIN(id), cat_id, title FROM table GROUP BY cat_id
SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT cat_id, MIN(id) id
FROM tableName
GROUP BY cat_id
) b ON a.cat_id = b.cat_id AND
a.id = b.id
ORDER BY a.cat_id

MySQL query with LIMIT in a descending order doesn't work with inner joint tables

So I have two tables that look like this:
table follows:
follower | following
-----------+-------------
1 | 2
-----------+-------------
1 | 3
-----------+-------------
2 | 1
-----------+-------------
1 | 4
-----------+-------------
(this is basically the table that contains which user follows which user on the site...the numbers are the user id-s)
table articles:
id | title | writer
------+-------------+---------
1 | a test | 2
------+-------------+---------
2 | testing | 3
------+-------------+---------
3 | another | 2
------+-------------+---------
4 | again | 4
------+-------------+---------
(id is an auto-increment field.. title contains the article's title.. writer contains the id of the user who wrote it)
Now I have a mysql query that looks like this:
SELECT * FROM follows f INNER JOIN articles a ON f.following = a.writer WHERE f.follower = 1 ORDER BY a.id DESC LIMIT 4, 2;
But I don't get any results
I would like to get those 2 articles out from the table that have an id that is SMALLER than 4. That is why I tried to put a DESC before LIMIT.
(So I want to get the articles that have the id 2 and 3.)
But it doesn't work. How could I do this? Please help! Thanks!
I would like to get those 2 articles out from the table that have an
id that is SMALLER than 4
Then try this:
SELECT *
FROM follows f
INNER JOIN
(
SELECT *
FROM articles
WHERE id > 1
OR id < 4
) a ON f.following = a.writer
WHERE f.follower = 1
ORDER BY a.id
Or:
SELECT *
FROM follows f
INNER JOIN articles a ON f.following = a.writer
WHERE f.follower = 1
AND (a.id > 1 OR a.id < 4 )
ORDER BY a.id
You are wrongly using LIMIT in your query. Your query returns 4 rows with all the articles written by authors you are following ordered by article.id desceding. But your LIMIT 4, 2 is skipping first 4 rows and then returning first 2 rows. As there are only 4 rows found, your result is empty.
Your result is ordered rightly, so if you want last two articles, you need to select first two rows:
SELECT *
FROM
test_follows f INNER JOIN test_articles a ON f.following = a.writer
WHERE
f.follower = 1
ORDER BY
a.id DESC
LIMIT 2
not sure if this is wat you want.. try this out.
mysql_query("SELECT * FROM follows f INNER JOIN articles a ON f.following = a.writer WHERE f.follower = 1 and a.id < 4 ORDER BY a.id ");
if get the articles. id smaller(lesser) than 4
hope this helps.