better alternative for this complex mysql query - mysql

I have two tables
1.fw_respondent_answers
2.fw_question_options
the structures are:
fw_respondent_answers
id invitationid qdetailid optionid
1 2 1 1
2 2 2 2
3 2 3 3
4 3 1 4
5 3 2 5
6 3 3 6
fw_question_options:
id optionname qdetailid
1 india 1
2 teacher 2
3 ok 3
4 france 1
5 assistane 2
6 good 3
Desired Output:
invitationid country profession answer
2 india teacher ok
3 france assistant good
Explanation:i want to get the optionname associated with a particular invitationid corresponding to the qdetailid and optionid.
optionid is the primary key of fw_question_options(id).
what i have tried:
SELECT distinct fra.`invitationid` ,fo.optionname as country,
fo1.optionname as profession,fo2.optionname as nps
FROM `fw_respondent_answers` fra,fw_question_options fo,
`fw_respondent_answers` fra1,fw_question_options fo1,
`fw_respondent_answers` fra2,fw_question_options fo2
WHERE fra.`optionid`=fo.id and fra.`qdetailid`=2
and fra1.`optionid`=fo1.id and fra1.`qdetailid`=1
and fra2.`optionid`=fo2.id and fra2.`qdetailid`=3
Question:my above query is very slow.i just want to know is there any other better alternative to the above query?
Thanks in advance.

Try this:
SELECT a.invitationid,
MAX(IF(a.qdetailid = 1, b.optionname, '')) AS country,
MAX(IF(a.qdetailid = 2, b.optionname, '')) AS profession,
MAX(IF(a.qdetailid = 3, b.optionname, '')) AS nps
FROM fw_respondent_answers a
INNER JOIN fw_question_options b ON a.optionid = b.id
GROUP BY a.invitationid

Related

How to Combine GROUP CONCAT with COUNT in MySQL?

I am trying to write a query that can get result from multiple tables:
Item Category
ic_id
ic_name
1
PC
2
Laptop
3
Printer
4
Scanner
Items
i_id
i_category
i_name
1
1
Dell Optiplex
2
2
HP Probook 450
3
2
HP Probook650
4
3
HP Laserjet 402dn
5
1
Dell MT3030
Item Sale
is_id
is_date
is_customer
1
15-03-2021
John
2
16-03-2022
Jimmy
3
18-03-2023
Mark
Item Sale Detail
isd_id
isd_sale_id
isd_item
1
1
2
2
1
3
3
2
4
4
3
1
5
3
5
6
3
4
Is it possible to get combined result of GROUP CONCAT with COUNT in 1 query? Please guide me to write the query to get the desired result, I want the query result as shown below, Thanks:
Desired Result
is_id
is_date
is_customer
items
1
15-03-2021
John
Laptop: 3
2
16-03-2022
Jimmy
Printer: 1
3
18-03-2023
Mark
PC:2 , Printer: 1
If I understand correctly, this is just join but with two levels of aggregation:
select its.*, ic.categories
from item_sale its join
(select isd.isd_sale_id,
group_concat(ic_name, ':', cnt order by cnt desc) as categories
from (select isd.isd_sale_id, ic.ic_name, count(*) as cnt
from item_sale_detail isd join
items i
on isd.isd_item = i.i_id join
item_category ic
on i.i_category = ic.ic_id
group by isd.isd_sale_id, ic.ic_name
) ic
group by isd.isd_sale_id
) ic
on i.is_id = ic.isd_sale_id;

Fetch rows which belonging to the parent category which has more than two rows

I have some combination of company and members
Member Table
id company_id companymember
1 1 john
2 1 Tam
3 2 haya
4 1 lee
5 3 kih
6 3 wild
7 3 cream
8 3 earth
What I want to pick up is
the 3 member names which belonging to the company which has more than two members
What I want is like this
company_id 2 has only 1 member, 3rd row is not selected
company_id 3 has 4 members, so 8th row is not selected
My Goal
1 1 john
2 1 Tam
4 1 lee
5 3 kih
6 3 wild
7 3 cream
I could make it , pick up company_ids first and
loop each id by script and fetch.
However in this way, it exec sql many times.
Is there any good way to do this on MySql by one sentence SQL??
Try this
select id,company_id,companyMember
from (Select id
,company_id
,companyMember
,Row_Number() OVER(PARTITION BY company_id ORDER By company_id) AS TotalCount
from MemberTable
) as Table1
where TotalCount <=3 and Company_id in(
Select Company_id
from MemberTable
group by Company_id
having COUNT(Company_id) >=3
)
order by id

MySQL query to extract email neighborhood

I have a MySQL table called personxmessage, extracted from emails. It has three fields, id (primary key), MessageID, and PersonID. For each message referenced by MessageID, there are two or more records, each with a PersonID for a person who was included in the email (i.e. in sender, sent to, or cc).
I want to query this table to get a link list showing all the people who were linked to a given PersonID=XXXX, and the links between them defined by being included on the emails that include XXXX, preferably including a weight on the links showing the number of occurrences. Another way of saying this, in graph terminology, is I'm trying to get the neighborhood of XXXX. For example, for entries like
MID PID
1 1
1 2
1 3
2 1
2 2
3 1
3 3
3 4
For PersonID 1 I would like to get link list
P1 P2 Count
1 1 3
1 2 2
1 3 2
1 4 1
2 3 1
3 4 1
Is it possible to do this with some kind of self-join? If so what query would I use? I have done some simpler joins (for example to get the star-graph of XXXX and other PersonIDs that are with XXXX on emails) but this one is over my head.
You can use GROUP_CONCAT do to something sort of like that. It's not a table but a result set of the related pids per mid.
select mid, group_concat(distinct pid order by pid separator ', ') as related_ppl
from personxmessage
group by mid;
result
mid related_ppl
1 1, 2, 3
2 1, 2
3 1, 3, 4
I think this is what you're looking for:
select p.pid as pid1, pp.pid as pid2, count(*) as cnt
from personxmessagep
left join personxmessagepp
on p.mid = pp.mid
and p.pid < pp.pid
group by p.pid, pp.pid;
result
pid pid2 cnt
1 2 2
1 3 2
1 4 1
2 1
2 3 1
3 1
3 4 1
4 1

MySQL - Get top 5 opponents

I am trying to get the top 5 opponents I played against.
The tables are as follow
USERS :
user_id name email
1 : Gait Bakker : user1#test.nl
2 : Freek ter Bekke : user2#test.nl
3 : Jan Zomer : user3#test.nl
4 : Mick Dundee : user4#test.nl
5 : Sjoerd Trekhaar : user#test.nl
GAMES :
game_id type training **created_by started_by **opponent_id won_by date
1 1 1 2 2 4 2 2015-08-10
2 1 1 5 2 2 5 2015-08-10
3 1 1 4 4 2 4 2015-08-10
3 1 1 2 3 3 3 2015-08-10
The problem is the fields with ** and that it needs to count the top 5 opponents.
I can be the game creator (created_by) and I can be the opponent_id (someone else started the game).
Still if I am the opponent I played against another player.
Edit
Please use user-id = 2 for example.
As additional : Training needs to be 1 and won_by IS NOT NULL (needs to be filled in)
Result SQL
Most played against opponent
user_id = 4, count = 2
user_id = 3, count = 1
user_id = 5, count = 1
So that means I played the most against user-id 4 and then user_id = 3 and user_id = 5
As per my Understanding, Top opponent will be considered based on the Won_By
SELECT TOP 5 NAME, COUNT(*) as COUNTS FROM USERS
INNER JOIN
GAMES
ON GAMES.WON_BY = USERS.user_id
WHERE user_id <> Logon_ID
GROUP BY NAME
ORDER BY COUNTS
Derive the Logon_ID according to your code

SELECT sql with four different tables with primary key and foreign key

For my database, having these four table
First one, DEPARTMENT
//DEPARTMENT
D# DNAME
------------------
1 RESEARCH
2 IT
3 SCIENCE
Second one, EMPLOYEE
//Employee
E# ENAME D#
-----------------------
1 ALI 1
2 SITI 2
3 JOHN 2
4 MARY 3
5 CHIRS 3
Third, PROJECT
//PROJECT
P# PNAME D#
-----------------------
1 Computing 1
2 Coding 3
3 Researching 3
Fourth, WORKSON
//WORKSON
E# P# Hours
--------------------
1 1 3
1 2 5
4 3 6
So my output should be something like
E# ENAME D# TOTAL HOURS/W
--------------------------------------------
1 ALI 1 8
2 SITI 2 0
3 JOHN 2 0
4 MAY 3 6
5 CHIRS 3 0
Display 0 because the employee has no project to works on.
my currently statement using
SELECT E#,ENAME,D# and sum(Hours) as TOTAL HOURS/W
FROM EMPLOYEE,PROJECT,WORKSON
WHERE EMPLOYEE.P#
no idea how should it select
You should use an left join like this. You only need 2 tables employee and workson.
Try this query:
SELECT e_tbl.E#, e_tbl.ENAME, e_tbl.D#,
coalesce(SUM(w_tbl.Hours), 0) as "Total Hours/W"
FROM
EMPLOYEE e_tbl LEFT JOIN WORKSON w_tbl
ON e_tbl.E# = w_tbl.E#
GROUP BY e_tbl.E#
You need to use GROUP BY and JOINS , in order to achieve your output
SELECT E.E#,
E.ENAME,
E.D#,
sum(Hours) AS TOTAL HOURS/W
FROM Employee AS E
JOIN WORKSON AS W ON E.E# = W.E#
GROUP BY E.E#,
E.ENAME,E.D#
Use this :)
With the given output you do not need to join all the tables, and this could be done by joining employee and works on as
select
e.`E#`,
e.ENAME,
e.`D#`,
coalesce(tot,0) as `TOTAL HOURS/W`
from Employee e
left join
(
select `E#`,
sum(Hours) as tot
from WORKSON
group by `E#`
)w
on w.`E#` = e.`E#`
group by e.`E#`
DEMO