How to make query on another query result in MYSQL? - php

I have made a query like that to get result by joining 3 tables
QUERY 1
SELECT a.user_id, a.nick_id, count(b.invoice_id) AS INVOICES, sum(b.purchase_amount) AS PURCHASES, c.sponsor_id, c.user_first_name, c.user_last_name
FROM table1 a
INNER JOIN table2 b ON a.user_id = b.user_id
INNER JOIN table3 c ON a.user_id = c.user_id
WHERE b.purchase_date BETWEEN '2018-09-01 00:00:00' AND now() and a.user_id IS NOT NULL GROUP BY a.user_id ORDER BY PURCHASES DESC
Table1 (Example)
user_id | nick_id
1 | AGENT1
2 | AGENT2
3 | AGENT3
Table2 (Example)
user_id | invoice_id | purchase_amount | purchase_date
1 | IN001 | 500 | 2018-09-01 14:58:33
2 | IN002 | 1000 | 2018-09-18 22:46:12
Table3 (Example)
user_id | sponsor_id | user_first_name | user_last_name
2 | 1 | John | Doe
3 | 1 | Harry | Wilson
4 | 2 | Peter | Bennington
5 | 2 | Daisy | Cooper
Now on the result of [QUERY 1], I want to perform [QUERY 2]
QUERY 2
SELECT sponsor_id, user_id, user_first_name, user_last_name
FROM
(SELECT * FROM table3 ORDER BY sponsor_id, user_id) table3,
(SELECT #pv := '1') initialisation WHERE find_in_set(sponsor_id, #pv) > 0
AND #pv := concat(#pv, ',', user_id)
After that I will get my desired result. But I want to perform both queries at once in a single query.

Related

Get Rank by votes and number of same rank PHP MySQL

i am trying to get rank and number of same rank by votes but unfortunately no success.
Here my table structure:
| ID| user_id | votes |
| --| ------- | ----- |
| 1 | D10 | 15 |
| 2 | D5 | 9 |
| 3 | D20 | 9 |
| 4 | D23 | 7 |
| 5 | D35 | 3 |
| 6 | D65 | 2 |
I need the rank of user according to votes, referring to above table i need the rank as:
| user_id | Rank|
| ------- | ----|
| D10 | 1 |
| D5 | 2 |
| D20 | 2 |
| D23 | 3 |
| D35 | 4 |
| D65 | 5 |
and also i need the number of rank, referring to above ranks i need:
Rank 1 = 1
Rank 2 = 2
Rank 3 = 1
Rank 4 = 1
rank 5 = 1
i tried to get rank :
SELECT user_id, votes, FIND_IN_SET( votes, (
SELECT GROUP_CONCAT( DISTINCT votes
ORDER BY votes DESC ) FROM table)
) AS rank
FROM votes
the above query i tried referring to this answer to get the ranks but i am getting error:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use
near '( votes , (SELECT GROUP_CONCAT( DISTINCT votes ORDER BY votes DESC
)
i need the desired result using PHP and MySQL.
On MySQL 8+ you could use windows function dense_rank and count over
with votes_rank as (
select *,
dense_rank() over (order by votes desc) as rnk
from votes
) , count_rank as
( select votes_rank.*,
count(*)over (partition by rnk) as cnt
from votes_rank
) select id,
user_id,
votes,
rnk as votes_rank,
cnt as count_rank
from count_rank;
https://dbfiddle.uk/o1DiPyDz
Consider the following data,
CREATE TABLE votes (
id int,
user_id varchar(10),
votes int );
insert into votes values (1,'D10',15), (2,'D5 ',9), (3,'D20',9), (4,'D23',7), (7,'D50',7), (5,'D35',3), (6,'D65',2);
Result:
id user_id votes votes_rank count_rank
1 D10 15 1 1
2 D5 9 2 2
3 D20 9 2 2
4 D23 7 3 2
7 D50 7 3 2
5 D35 3 4 1
6 D65 2 5 1
Edit,
On MySQL version <8
select tbl.id,tbl.user_id,tbl.votes,tbl.rnk,votes_count
from (SELECT a.id,
a.user_id,
a.votes,
count(b.votes)+1 as rnk
FROM votes a
left join votes b on a.votes<b.votes
group by a.id,a.user_id,a.votes
order by a.votes desc
) as tbl
inner join (select rnk,count(rnk) as votes_count
from ( SELECT a.id,
a.user_id,
a.votes,
count(b.votes)+1 as rnk
FROM votes a
left join votes b on a.votes<b.votes
group by a.id,a.user_id,a.votes
order by a.votes desc
) a2
group by rnk
) as tbl1 on tbl1.rnk = tbl.rnk;
https://dbfiddle.uk/XlsBjrZO

Stuck in building MySQL query

Given an example of table:
id | item_id | user_id | bid_price
----------------------------------
The task is to select rows with minimum bid_price for each item_id in the provided set.
For example: item_id = [1, 2, 3] - so I need to select up to three (3) rows, having a minimum bid_price.
Example of data:
id | item_id | user_id | bid_price
----------------------------------
1 | 1 | 11 | 1
2 | 1 | 12 | 2
3 | 1 | 13 | 3
4 | 1 | 14 | 1
5 | 1 | 15 | 4
6 | 2 | 16 | 2
7 | 2 | 17 | 1
8 | 3 | 18 | 2
9 | 3 | 19 | 3
10 | 3 | 18 | 2
Expected result:
id | item_id | user_id | bid_price
----------------------------------
1 | 1 | 11 | 1
7 | 2 | 17 | 1
8 | 3 | 18 | 2
Actually, I'm using Symfony/Docine DQL, but it will be enough with a plain SQL example.
For the all the columns in the rows you could use a inner join on subselect for min bid price
select m.id, m.item_id, m.user_id, m.bid_price
from my_table m
inner join (
select item_id, min(id) min_id, min(bid_price) min_price
from my_table
where item_id IN (1,2,3)
group by item_id
) t on t.item_id = m.item_id
and t.min_price= m.bid_price
and t.min_id = m.id
or .. if you have some float data type you could use a acst for unsigned
select m.id, m.item_id, m.user_id, cast(m.bid_price as UNSIGNED)
from my_table m
inner join (
select item_id, min(id) min_id, min(bid_price) min_price
from my_table
where item_id IN (1,2,3)
group by item_id
) t on t.item_id = m.item_id
and t.min_price= m.bid_price
and t.min_id = m.id
You can use MIN() with GROUP BY in the query:
SELECT id, item_id, MIN(bid_price) AS min_bid, user_id
FROM your_tbl
GROUP BY item_id
HAVING item_id in(1, 2, 3);
Use this query:
SELECT id, item_id, user_id, min(bid_price) as bid_price
FROM YOUR_TABLE_NAME
GROUP BY item_id;

mysql count how many times the same value appears across multiple colums

during a group project we recent sent out a survey regarding the site we're building. I've put the data into a mysql database and i'm trying to figure out how to count how many times certain scores was given in each category
the table looks like this
+-----------------+--------------+-------------------+
| Design | Ease of use | Responsiveness |
+-----------------+--------------+-------------------+
| 5 | 5 | 5
| 4 | 4 | 4
| 3 | 3 | 3
| 2 | 2 | 2
| 1 | 1 | 1
| 5 | 4 | 2
| 5 | 4 | 4
| 3 | 3 | 3
| 1 | 2 | 2
| 1 | 2 | 2
I've found a query that works for one colum
SELECT Design, COUNT(*) AS num FROM table GROUP BY Design
I would then get
Design | num
-------------
5 | 3
4 | 1
3 | 2
2 | 1
1 | 3
If i were to try
SELECT Design, COUNT(*) AS num1, Ease of use, COUNT(*) as num2 FROM table
GROUP BY Design, Ease of use
The table gets totally messed up.
What I want is to get
Design | num1 | Ease of use | num2 | Responsiveness | num3
------------- --------------------------------------------------
5 | 3 | 5 | 1 | 5 | 1
4 | 1 | 4 | 3 | 4 | 2
3 | 2 | 3 | 2 | 3 | 2
2 | 1 | 2 | 3 | 2 | 4
1 | 3 | 1 | 1 | 1 | 1
Any help would be greatly appreciated
You can unpivot the values and then aggregate. In MySQL, that typically uses union all:
select val, count(*)
from ((select design as val from table) union all
(select ease_of_use from table) union all
(select responsiveness from table
) der
group by val
order by val desc;
For what you want to get, you can do:
select val, sum(design) as design, sum(ease_of_use) as ease_of_use,
sum(responsiveness) as responsiveness
from ((select design as val, 1 as design, 0 as ease_of_use, 0 as responsiveness from table) union all
(select ease_of_use, 0, 1, 0 from table) union all
(select responsiveness, 0, 0, 1 from table
) der
group by val
order by val desc;
I see no reason to repeat the value three times.
Use a synthesized table with the different values, and join this with subqueries that get the counts of each score.
SELECT nums.num AS Design, t1.count AS num1,
nums.num AS `Ease of Use`, t2.count AS num2,
nums.num AS Responsiveness, t3.count AS num3
FROM (SELECT 1 AS num UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) AS nums
LEFT JOIN (
SELECT Design, COUNT(*) AS count
FROM yourTable
GROUP BY Design) AS t1 ON t1.Design = nums.num
LEFT JOIN (
SELECT `Ease of Use`, COUNT(*) AS count
FROM yourTable
GROUP BY `Ease of Use`) AS t2 ON t2.`Ease of Use` = nums.num
LEFT JOIN (
SELECT Responsiveness, COUNT(*) AS count
FROM yourTable
GROUP BY Responsiveness) AS t3 ON t3.Responsiveness = nums.num
DEMO
Here are three ways:
select s.score,
(select count(*) from tbl where `Design` = s.score) as `Design`,
(select count(*) from tbl where `Ease of use` = s.score) as `Ease of use`,
(select count(*) from tbl where `Responsiveness` = s.score) as `Responsiveness`
from (
select Design as score from tbl
union select `Ease of use` from tbl
union select Responsiveness from tbl
) s
order by score desc
http://sqlfiddle.com/#!9/002303/2
select s.score,
(select count(*) from tbl where `Design` = s.score) as `Design`,
(select count(*) from tbl where `Ease of use` = s.score) as `Ease of use`,
(select count(*) from tbl where `Responsiveness` = s.score) as `Responsiveness`
from (select 1 as score union select 2 union select 3 union select 4 union select 5) s
order by score desc
http://sqlfiddle.com/#!9/002303/4
select s.score,
sum(`Design` = score) as `Design`,
sum(`Ease of use` = score) as `Ease of use`,
sum(`Responsiveness` = score) as `Responsiveness`
from (select 1 as score union select 2 union select 3 union select 4 union select 5) s
cross join tbl t
group by s.score
order by s.score desc
http://sqlfiddle.com/#!9/002303/5
They all return the same result:
| score | Design | Ease of use | Responsiveness |
|-------|--------|-------------|----------------|
| 5 | 3 | 1 | 1 |
| 4 | 1 | 3 | 2 |
| 3 | 2 | 2 | 2 |
| 2 | 1 | 3 | 4 |
| 1 | 3 | 1 | 1 |
As #futureweb wrote in the comment, I don't see a reason to repeat the score three times. Though you can if you want using aliases.
If you have millions of rows ;-) and no indexes you would want to get the result with only one table scan. This is possible with:
select
sum(`Design` = 1) as d1,
sum(`Design` = 2) as d2,
sum(`Design` = 3) as d3,
sum(`Design` = 4) as d4,
sum(`Design` = 5) as d5,
sum(`Ease of use` = 1) as e1,
sum(`Ease of use` = 2) as e2,
sum(`Ease of use` = 3) as e3,
sum(`Ease of use` = 4) as e4,
sum(`Ease of use` = 5) as e5,
sum(`Responsiveness` = 1) as r1,
sum(`Responsiveness` = 2) as r2,
sum(`Responsiveness` = 3) as r3,
sum(`Responsiveness` = 4) as r4,
sum(`Responsiveness` = 5) as r5
from tbl
This will return the data you need, but not in the form you'd like:
| d1 | d2 | d3 | d4 | d5 | e1 | e2 | e3 | e4 | e5 | r1 | r2 | r3 | r4 | r5 |
|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|
| 3 | 1 | 2 | 1 | 3 | 1 | 3 | 2 | 3 | 1 | 1 | 4 | 2 | 2 | 1 |
So you would need to post process it.

mySQL query: order by group points by sum of join member points

I got 2 tables which are linked.
GROUPS can have multiple USERS and USERS can be in multiple GROUPS.
GROUPS
|id| name |
----------------
|1| Koalas |
|2| Grizzlies |
|3| Hornets |
----------------
USERS
|id| firstName | points |
----------------
|1| Bob | 2
|2| Hans | 4
|3| Jerome | 1
|4| Katy | 6
----------------
GROUP_USER
|id| group_id | user_id |
--------------------------
|1| 1 | 2
|2| 1 | 4
|3| 2 | 1
|4| 2 | 2
|5| 3 | 3
|6| 3 | 4
----------------
Now I want to rank the groups by the points of their members.
Result:
GROUP_USER
|rank| group_name | user_points |
-----------------------------------
|1 | Koalas | 10
|2 | Hornets | 7
|3 | Grizzlies | 6
DonĀ“t really know how to start.
select #rank := #rank + 1 as rank, name, user_points
from
(
select g.name,
sum(u.points) as user_points
from groups g
left join group_user gu on gu.group_id = g.id
left join users u on gu.user_id = u.id
group by g.name
order by user_points desc
) tmp
cross join (select #rank := 0) r

JOIN 2 tables without records replication

I have 2 tables:
1:
id | name
1 | test
2 | test1
2.
id | related_id | additional
1 | 1 | 1
2 | 1 | 2
id in 1 table relates with related_id in 2
How to JOIN 1 table with 2 without replication records, so the result will be only 1 row from second table (related_id and additional can be any)
id | name | related_id | additional
1 | test | 1 | 1
2 | test1| NULL | NULL
Update
IF I try to group after INNER/LEFT JOIN, the result is
id | name | related_id | additional
1 | test | 1 | 1
You can group the result with the primary key
select *
from table1 left join table2
on table1.id = table2.related_id
group by table1.id
You can use a join
SELECT
*
FROM table1 as t1
LEFT JOIN (
SELECT
MAX(id),
related_id
FROM table2
) as t2
ON t1.id = t2.related_id

Categories