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
Related
If I have agents that can have many properties, and vice versa, defined in a in a junction table, how would I query the top agents (an agent who has at least two properties in common with two other agents.)
agent
id
1
2
3
4
5
properties
id
1
2
3
4
5
6
agent_properties
agent_id
property_id
1
1
1
2
1
3
2
2
2
3
3
1
3
3
3
5
4
3
4
4
4
6
5
1
5
2
5
5
6
4
6
6
Example:
Agent 1 (propr1, propr2, propr3),
Agent 2 (propr2, propr3),
Agent 3 (propr1, propr3, propr5)
Agent 4 (propr3, propr4, propr6)
Agent 5 (propr1, propr2, propr5)
Agent 6 (propr4, propr6)
So the query should return Agent 1, Agent 3, Agent 5
If anyone can show how to do this using Laravel Eloquent that would be great.
A solution would be to work with bits.
First you should add a new column in table properties and this new column to be named bin_value. The values from this column must be unique per property and to be power of 2. In your case would be:
id
bin_value
1
1
2
2
3
4
4
8
5
16
6
32
Second, add a new column to agent table named properties and run following update query:
UPDATE agent AS a
INNER JOIN (
SELECT ap.agent_id, SUM(p.bin_value) AS bin_properties
FROM agent_properties AS ap
INNER JOIN properties AS p ON p.id = ap.property_id
GROUP BY ap.agent_id
) AS b ON a.id = b.agent_id
SET a.properties = b.bin_properties
;
Third, run the query with bit function which helps you to find agents which have at least 2 shared properties with at least 2 other agents:
SELECT a1.agent_id
, a1.name
, COUNT(*) AS total_other_agents
FROM agent AS a1
INNER JOIN agent AS a2 ON a1.id != a2.id
AND BIT_COUNT(a1.properties & a2.properties) >= 2 -- at least 2 shared properties
GROUP BY a1.id
HAVING total_other_agents >= 2 -- at least 2 other agents
ORDER BY total_other_agents DESC, a1.name
;
If you have a large number of properties try to set values in bin_value like this:
UPDATE properties
SET bin_value = BINARY(POWER(2, id-1))
;
I have over 1100+ records in my people (table) and i would like to filter those who are under a specific place (table) record and would update a newly inserted column value named people_identifier_num of people table.
Place table
id name desc
1 Place 1 some description.
2 Place 2 some description..
3 Place 3 some description...
People table
id name place_id people_identifier_num
1 People 1 1 null
2 People 2 1 null
3 People 3 2 null
4 People 4 2 null
5 People 5 2 null
6 People 6 2 null
7 People 7 3 null
... ... ... ....
1100 People 1100 2 null
Now i would like to assign a pin (people_identifier_num) to every person that belongs to a particular place which begin with value 1 and so on..
E.g.
id name place_id people_identifier_num
3 People 3 2 1
4 People 4 2 2
5 People 5 2 3
6 People 6 2 4
... ... ... ....
E.g.
id name place_id people_identifier_num
1 People 1 1 1
2 People 2 1 2
... ... ... ....
My current solution is to filter people by place and sort it by name alphabetically. However how can we write a SQL script that loop each filtered record and assign the pin value starting from 1 and so on?
You can use rank query to assign pin no. to each people according to their place
update people
join (
select p.id,place_id,name,
case when #place = place_id then #row:= #row +1 else #row:= 1 end rank,
#place:= place_id
from (
select * from people,(select #place:=null,#row:=1) t order by place_id,name
) p
) p1
using(place_id,name)
set people_identifier_num = p1.rank;
Demo
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
Considering the following query:
SELECT t.recording_id, m.release_id
FROM track t
JOIN medium m ON t.medium_id = m.medium_id
i get a result set similar to this one
recording id release id
----------------------------------
1 25
1 25
1 37
1 76
1 300
1 336
2 37
... ...
i need to output the following
recording id count
---------------------------------------------------
1 5
2 1
In other words, i need to group by the recording_id but not count the release_id duplicates for that recording_id
After researching this board i've tried the following, with no success :
SELECT t.recording_id, count(t.recording_id)
FROM track t
JOIN medium m ON t.medium_id = m.medium_id
group by t.recording_id, m.release_id
but, im getting
recording id release id
--------------------------
1 2
1 1
1 1
1 1
1 1
2 1
What's wrong?
Try this, you can use distinct in your count function to return distinct release ids for a recording_id
SELECT t.recording_id, count(distinct m.release_id) cnt
FROM track t
JOIN medium m ON t.medium_id = m.medium_id
group by t.recording_id
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