get count of rows where user id w.r.t to sender - mysql

I have built a private messaging system :
CREATE TABLE if not exists tblA
(
id int(11) NOT NULL auto_increment ,
sender varchar(255),
receiver varchar(255),
msg varchar(255),
date timestamp,
PRIMARY KEY (id)
);
INSERT INTO tblA (sender, receiver,msg,date ) VALUES
('1', '2', 'buzz ...','2011-08-21 14:11:09'),
('1', '2', 'test ...','2011-08-21 14:12:19'),
('1', '2', 'check ...','2011-08-21 14:13:29'),
('1', '1', 'test2 ...','2011-08-21 14:14:09'),
('2', '1', 'check2 ...','2011-08-21 14:15:09'),
('2', '1', 'test3 ...','2011-08-21 14:16:09'),
('1', '2', 'buzz ...','2011-08-21 14:17:09'),
('1', '2', 'test ...','2011-08-21 14:18:19'),
('1', '2', 'check ...','2011-08-21 14:19:29'),
('1', '1', 'test2 ...','2011-08-21 14:10:09'),
('3', '1', 'check2 ...','2011-08-21 14:21:09'),
('3', '1', 'test3 ...','2011-08-21 14:22:09'),
('3', '2', 'buzz ...','2011-08-21 14:24:09'),
('3', '2', 'test ...','2011-08-21 14:25:19'),
('1', '3', 'check ...','2011-08-21 14:26:29'),
('1', '3', 'test2 ...','2011-08-21 14:27:09'),
('2', '3', 'check2 ...','2011-08-21 14:28:09'),
('2', '3', 'test3 ...','2011-08-21 14:29:09'),
('1', '2', 'check3 ...','2011-08-21 14:23:09');
How to get count of user interatcing with sender and vice versa for different user.For eg: 1-2,2-1 is same count and 1-1 is same count and 1-3,3-1 is same count and 2-3,3-2 is same count.Basically count of all interactions between the user-sender,sender-user .
Desired output (if I am user 1)
sender receiver count
3 1 4
1 1 2
2 1 9
I really appreciate any help.Thanks in Advance.

The original answer is gone, so allow me to post this again:
SELECT
LEAST(sender, receiver) as X,
GREATEST(sender, receiver) as Y,
COUNT(1)
FROM
tblA
GROUP BY
X, Y;
This will select every set of interaction between two people. As you requested, you won't be able to tell who contacted who. You'll just be able to tell how many interactions there have been between two people.
And here's the fiddle I did yesterday.

this i think works and outputs what you asked. I'm not a fan of the squared group by, because for example 23*23+89*89 = 8450 = 13*13 + 91*91 (but i might have missed something)
select one, two, if(one=two,sum(cnt)/2,sum(cnt)) AS NUMBER from
(
select sender as one,receiver as two, count(*) as cnt from tblA group by sender, receiver
union all
select receiver as one ,sender as two, count(*) as cnt from tblA group by sender, receiver
) a
group by one, two
order by one, two
http://sqlfiddle.com/#!2/9d150/15

Related

Ties on Hall of Fame (group player, max level then max score for each game when month is...)

Need to list a Hall of Fame of best players, the database contains each single game player in different games.
The level has the priority, if the level are the same, check the highest score.
I've a database with user_id, level, score, game and data. Schema here:
CREATE TABLE IF NOT EXISTS `docs` (`user_id` int(6) unsigned NOT NULL,
`level` int(3) unsigned NOT NULL,`game` varchar(30) NOT NULL,
`score` int(5) unsigned NOT NULL,
`data` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `docs` (`user_id`, `level`, `game`, `score`,`data`) VALUES
('1', '7', 'pacman', '8452','2018-02-14 15:00:00'),
('1', '9', 'pacman', '9999','2018-02-10 16:30:00'),
('2', '8', 'pacman', '8500','2018-02-24 17:30:00'),
('1', '10', 'pacman', '9100','2018-02-15 18:30:00'),
('1', '10', 'pacman', '8800','2018-02-15 18:11:00'),
('1', '11', 'snake', '9600','2018-02-14 15:00:00'),
('1', '6', 'snake', '7020','2018-02-11 11:30:00'),
('2', '8', 'snake', '8500','2018-02-24 14:00:00'),
('2', '12', 'snake', '9200','2018-02-25 19:00:00'),
('2', '12', 'snake', '9800','2018-02-25 19:20:00'),
('1', '4', 'pacman', '2452','2018-03-11 15:00:00'),
('1', '6', 'pacman', '4999','2018-03-07 16:30:00'),
('2', '7', 'pacman', '5500','2018-03-02 17:30:00'),
('1', '7', 'pacman', '5100','2018-03-01 18:30:00'),
('1', '3', 'snake', '3600','2018-03-03 15:00:00'),
('1', '5', 'snake', '4220','2018-03-01 11:30:00'),
('2', '5', 'snake', '3900','2018-03-04 14:00:00'),
('2', '5', 'snake', '5200','2018-03-05 19:00:00');
i want retrieve the hall of fame for selected month and game,
for example if i choose pacman on march the result should be:
user level score
2 7 5500
1 7 5100
i tryed this how suggest in other similar topic
select d1.*
from docs d1
left outer join docs d2
on (d1.user_id = d2.user_id and d1.level < d2.level)
where d2.user_id is null
order by level desc;
but i've duplicate levels for same user, then i cant choose the game or the month.
here there is the SQL Fiddle
SELECT x.* FROM docs x
JOIN
(select user_id
, game
, MONTH(data) month
, MAX(score) score
from docs
where game = 'pacman'
and MONTH(data) = 3
group
by user_id
, game
, MONTH(data)
) y
ON y.user_id = x.user_id
AND y.game = x.game
AND y.month = MONTH(x.data)
AND y.score = x.score;
or something like that
after a long work, study and research this is the best solution for me:
SELECT user_id, level, score, game
FROM (
SELECT *,
#rn := IF(user_id = #g, #rn + 1, 1) rn,
#g := user_id
FROM (select #g := null, #rn := 0) x,
docs where game='pacman'
ORDER BY user_id, level desc, score desc, game
) X
WHERE rn = 1 order by level desc, score desc;
the explanation is in this topic Select one value from a group based on order from other columns

Summing in mysql previous row with current

Need help to make query.
I have table like this:
kli, akt, mes
'2', '2', '201209'
'2', '2', '201210'
'3', '3', '201211'
And I need a result table:
kli, akt, mes
'2', '2', '201209'
'4', '4', '201210'
'7', '7', '201211'
result tables sum by field mes, current and all previous rows
try the below query
SELECT SUM(b.kli),SUM(b.akt),a.mes FROM tableName a INNER JOIN tableName b ON a.mes >= b.mes GROUP BY a.mes

SQL nested select sum returns wrong integer

I have the following select statement:
SELECT
T.name,
C.name as competence_name,
THC.competence_level_id as requiredLevel,
(SELECT SUM(UHC.competence_level_id) FROM user_has_competence UHC INNER JOIN user U ON U.id = UHC.user_id WHERE competence_id = C.id AND U.title_id = T.id GROUP BY T.id) as current_level,
(SELECT
ROUND(SUM(UHC.competence_level_id)/ COUNT(UHC.user_id))
FROM
user_has_competence UHC
JOIN user U ON U.id = UHC.user_id
WHERE
competence_id = C.id
AND U.title_id = T.id GROUP BY T.id) - THC.competence_level_id as gap,
C.id
FROM
title_has_competence THC
JOIN
title T ON T.id = THC.title_id
JOIN
competence C ON C.id = THC.competence_id
This returns the following result:
'Head of IT', 'Office', '7', '16', '1', '524'
'Head of IT', 'Empatisk', '2', '5', '1', '527'
'Head of IT', 'Målrettet', '5', '12', '1', '529'
'Head of IT', 'Udadvendt', '10', NULL, NULL, '525'
'Webudvikler', 'Office', '2', '3', '1', '524'
'Webudvikler', 'Outlook', '3', '4', '1', '526'
'Webudvikler', 'Målrettet', '6', '10', '4', '529'
'Webudvikler', 'Back-end', '9', '9', '0', '534'
'Webudvikler', 'Infosoft', '10', '5', '-5', '532'
However the result is invalid:
In the first row you will see the current level sum is = 16 this should be 9 (6 + 3)
The gap is also incorrect as the gap should be 9 / 2 = 4.5 - 7 = -2.5
So my question is what am i doing wrong? why is my SUM() function returning way to much.
Also note that the COUNT() returns the right value = 2
The Tables
title_has_competence
id title_id competence_id competence_level_id
'82', '165', '527', '2'
'85', '166', '524', '2'
'86', '166', '526', '3'
'83', '165', '529', '5'
'87', '166', '529', '6'
'81', '165', '524', '7'
'88', '166', '534', '9'
'84', '165', '525', '10'
'89', '166', '532', '10'
User_has_competence
user_id, competence_id, competence_level_id, progression
'1', '524', '6', '0'
'1', '527', '4', '0'
'1', '529', '3', '0'
'2', '524', '10', '0'
'2', '527', '1', '0'
'2', '529', '9', '0'
'3', '524', '3', '0'
'3', '526', '4', '0'
'3', '529', '10', '0'
'3', '532', '5', '0'
'3', '534', '9', '0'
title
id, name organization_id
'165', 'Head of IT', '1'
'166', 'Webudvikler', '1'
User
id, username, password, title_id,
1 ** , ** , 165
2 ** , ** , 165
3 ** , ** , 166

Use nested subquery to fetch value with multiple condition

I have a table named test_plan (id, unit, num)
I inserted some values
INSERT INTO `test_plan` (`id`, `unit`, `num`) VALUES
('1', '1', '12'),
('2', '1', '13'),
('3', '1', '14'),
('4', '1', '10'),
('5', '2', '10'),
('6', '2', '9'),
('7', '2', '-1'),
('8', '2', '-1'),
('9', '2', '-1'),
('10', '3', '-1'),
('11', '3', '-1'),
('12', '3', '-1');
I have to fetch unit what is fraction of each unit to total unit when num is not equals to -1
i.e.after run the query it display as unit 1 is 100% completed, unit 2 is 40% completed, unit 3 is 0% completed as row wise. I can count the number of each unit but not the how much it completed.
I tried JOIN for this
SELECT a.unit, numb / count(*) as frac FROM test_plan as a
LEFT OUTER JOIN (SELECT unit, count(num) as numb FROM test_plan where num != -1 group by unit) as b
ON a.unit = b.unit group by a.unit;
try this:
select unit,
(sum(case when num = -1 then 0 else 1 end) / count(*)) * 100 as pct_complete
from lecture_plan group by unit;
there's no need for a nested sub query, the combination of aggregation and the case statement is sufficient

mysql query hierarchic

I need help to find a sql query
CREATE TABLE album (
id_album INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
nom VARCHAR(255) NOT NULL
);
CREATE TABLE sous_album (
id_sous_album INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
nom VARCHAR(255) NOT NULL,
id_album INTEGER REFERENCES album(id_album)
);
CREATE TABLE photo (
id_photo INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
nom VARCHAR(255) NOT NULL,
id_sous_album INTEGER REFERENCES sous_album(id_sous_album)
);
INSERT INTO album(id_album, nom) VALUES
('1', 'album1'),
('2', 'album2'),
('3', 'album3')
;
INSERT INTO sous_album(id_sous_album, nom, id_album) VALUES
('1', 'sous album 1', '1'),
('2', 'sous album 2', '1'),
('3', 'sous album 3', '1'),
('4', 'sous album 4', '2'),
('5', 'sous album 5', '2'),
('6', 'sous album 6', '3')
;
INSERT INTO photo(id_photo, nom, id_sous_album) VALUES
('1', 'photo1', '1'),
('2', 'photo2', '1'),
('3', 'photo3', '1'),
('4', 'photo4', '1'),
('5', 'photo5', '2'),
('6', 'photo6', '2'),
('7', 'photo7', '3'),
('8', 'photo8', '3'),
('9', 'photo9', '3'),
('10', 'photo10', '4'),
('11', 'photo11', '5'),
('12', 'photo12', '6'),
('13', 'photo13', '6'),
('14', 'photo14', '6'),
('15', 'photo15', '6')
;
SELECT distinct album.nom, count(photo.id_photo)
from album, photo, sous_album
where album.id_album=sous_album.id_album
AND sous_album.id_sous_album=photo.id_sous_album
group by album.nom
order by album.nom`
this query give me the name of the album and the number of photos but i want also the sous album and their numbers of photo... can u help me ?
the result :
nom | count(photo.id_photo)
album1 | 9
album2 | 2
album3 | 4
i need this result :
nom | count(photo.id_photo)
album1 | 9
sous album 1 | 4
sous album 2 | 2
sous album 3 | 3
album2 | 2
sous album 4 | 1
sous album 5 | 1
album3 | 4
sous album 6 | 4
SELECT x.*
, y.*
FROM
( SELECT a.nom
, COUNT(*) total
FROM album a
JOIN sous_album ap
ON ap.id_album = a.id_album
JOIN photo p
ON p.id_sous_album = ap.id_sous_album
GROUP
BY a.nom
) x
JOIN
( SELECT a.nom nom_album
, ap.nom nom_sous_ablum
, COUNT(*) total
FROM album a
JOIN sous_album ap
ON ap.id_album = a.id_album
JOIN photo p
ON p.id_sous_album = ap.id_sous_album
GROUP
BY a.nom
, ap.nom
) y
ON y.nom_album = x.nom;
Note that this particular query will only return an album if there is at least one sous_album (and photo) associated with it.
thanks for your solution... i find a other one...
SELECT a.nom, sa.nom, COUNT( * ) AS NbPhoto FROM album a INNER JOIN sous_album sa ON sa.id_album = a.id_album INNER JOIN photo p ON p.id_sous_album = sa.id_sous_album GROUP BY a.nom, sa.nom WITH ROLLUP