I asked a question and received a great solution from #O. Jones, thank you very much.
Statistics With Tcl And Mysql
Unfortunately I had to expand the mysql datanbank with a column building
I need now in addition, name to each, the building, the most benutt
as an example, at work1, A1 is the most used building, at work2 is B1
ID key ctime name floor floorid door building
1 114554737 1609613062 work1 1 D1 112 A1
2 114554737 1609662335 work1 1 D1 112 A1
3 114554737 1609662388 work1 1 D1 115 A2
4 114554737 1609665480 work1 2 D1 201 C1
5 114554738 1609701179 work2 2 D1 202 A1
6 114554738 1609701188 work2 1 D1 101 B1
7 114554738 1609701195 work2 2 D1 225 B1
8 114554738 1609701253 work2 3 D1 318 B1
9 114554738 1609707953 work2 4 D1 412 C1
10 114554738 1609876824 work2 5 D1 500 C1
11 114554739 1609956064 work3 1 D1 100 C1
12 114554739 1609956067 work3 1 D1 101 A1
13 114554739 1610084925 work3 1 D1 100 A1
14 114554739 1610084928 work3 1 D1 100 A1
15 114554740 1610141106 work4 2 D1 201 A1
16 114554740 1610141109 work4 2 D1 202 A1
17 114554740 1610177322 work4 2 D1 202 A1
18 114554740 1610178412 work4 2 D1 202 A1
19 114554740 1610207104 work4 2 D1 202 A1
20 114554741 1610216851 work5 2 D1 202 A1
21 114554741 1610268582 work5 2 D1 202 A1
22 114554741 1610268908 work5 2 D1 202 A1
23 114554741 1610271923 work5 2 D1 206 A1
24 114554741 1610275117 work5 2 D1 206 A1
25 114554741 1610293137 work5 3 D1 301 A1
I use this query from the answer from O. Jone
set sql {SELECT t.name, t.total, d.details
FROM (SELECT COUNT(*) total, name FROM stats GROUP BY name) t
JOIN ( SELECT name,
GROUP_CONCAT(CONCAT(bydoor,'X',' door ', door) ORDER BY bydoor DESC) details
FROM ( SELECT COUNT(*) bydoor,
name,
door
FROM stats
GROUP BY name, door
) s
GROUP BY name
) d ON t.name = d.name
ORDER BY t.total DESC, t.name}
One Prblem with the count of objects is, what to do if there are two buildings with the same count.
I changed the data to demonstrate the problem.
GORUP_CONCAT has also the possibility to order by any column available
for example GROUP_CONCAT(buildingORDER BYbuilding) AS building``
CREATE TABLE stats (
`ID` INTEGER,
`key` INTEGER,
`ctime` INTEGER,
`name` VARCHAR(5),
`floor` INTEGER,
`floorid` VARCHAR(2),
`door` INTEGER,
`building` VARCHAR(2)
);
INSERT INTO stats
(`ID`, `key`, `ctime`, `name`, `floor`, `floorid`, `door`, `building`)
VALUES
('1', '114554737', '1609613062', 'work1', '1', 'D1', '112', 'A1'),
('2', '114554737', '1609662335', 'work1', '1', 'D1', '112', 'A1'),
('3', '114554737', '1609662388', 'work1', '1', 'D1', '115', 'A2'),
('3', '114554737', '1609662388', 'work1', '1', 'D1', '115', 'A2'),
('4', '114554737', '1609665480', 'work1', '2', 'D1', '201', 'C1'),
('5', '114554738', '1609701179', 'work2', '2', 'D1', '202', 'A1'),
('6', '114554738', '1609701188', 'work2', '1', 'D1', '101', 'B1'),
('7', '114554738', '1609701195', 'work2', '2', 'D1', '225', 'B1'),
('8', '114554738', '1609701253', 'work2', '3', 'D1', '318', 'B1'),
('9', '114554738', '1609707953', 'work2', '4', 'D1', '412', 'C1'),
('10', '114554738', '1609876824', 'work2', '5', 'D1', '500', 'C1'),
('11', '114554739', '1609956064', 'work3', '1', 'D1', '100', 'C1'),
('12', '114554739', '1609956067', 'work3', '1', 'D1', '101', 'A1'),
('13', '114554739', '1610084925', 'work3', '1', 'D1', '100', 'A1'),
('14', '114554739', '1610084928', 'work3', '1', 'D1', '100', 'A1'),
('15', '114554740', '1610141106', 'work4', '2', 'D1', '201', 'A1'),
('16', '114554740', '1610141109', 'work4', '2', 'D1', '202', 'A1'),
('17', '114554740', '1610177322', 'work4', '2', 'D1', '202', 'A1'),
('18', '114554740', '1610178412', 'work4', '2', 'D1', '202', 'A1'),
('19', '114554740', '1610207104', 'work4', '2', 'D1', '202', 'A1'),
('20', '114554741', '1610216851', 'work5', '2', 'D1', '202', 'A1'),
('21', '114554741', '1610268582', 'work5', '2', 'D1', '202', 'A1'),
('22', '114554741', '1610268908', 'work5', '2', 'D1', '202', 'A1'),
('23', '114554741', '1610271923', 'work5', '2', 'D1', '206', 'A1'),
('24', '114554741', '1610275117', 'work5', '2', 'D1', '206', 'A1'),
('25', '114554741', '1610293137', 'work5', '3', 'D1', '301', 'A1');
SELECT
t.name, t.total, d.details, t1.`building`
FROM
(SELECT
COUNT(*) total, name
FROM
stats
GROUP BY name) t
JOIN
(SELECT
name,
GROUP_CONCAT(CONCAT(bydoor, 'X', ' door ', door)
ORDER BY bydoor DESC) details
FROM
(SELECT
COUNT(*) bydoor, name, door
FROM
stats
GROUP BY name , door) s
GROUP BY name) d ON t.name = d.name
INNER JOIN
(SELECT
`name`,
GROUP_CONCAT(`building`) AS `building`,
buildingcount
FROM
(SELECT
`name`, `building`, COUNT(`building`) buildingcount
FROM
stats s
GROUP BY name , `building`
HAVING buildingcount = (SELECT
COUNT(`building`)
FROM
stats
WHERE
`name` = s.`name`
GROUP BY name , `building`
ORDER BY COUNT(`building`) DESC
LIMIT 1)) t3
GROUP BY `name` , buildingcount) t1 ON t1.`name` = t.`name`
ORDER BY t.total DESC , t.name
name | total | details | building
:---- | ----: | :---------------------------------------------------------------------- | :-------
work2 | 6 | 1X door 500,1X door 412,1X door 318,1X door 225,1X door 202,1X door 101 | B1
work5 | 6 | 3X door 202,2X door 206,1X door 301 | A1
work1 | 5 | 2X door 115,2X door 112,1X door 201 | A2,A1
work4 | 5 | 4X door 202,1X door 201 | A1
work3 | 4 | 3X door 100,1X door 101 | A1
SELECT `name`,GROUP_CONCAT(`building`), buildingcount
FROM
(SELECT `name`, `building`,COUNT(`building`) buildingcount
FROM stats s
GROUP BY name,`building`
HAVING buildingcount = (SELECT COUNT(`building`) FROM stats WHERE `name` = s.`name`
GROUP BY name,`building`
ORDER BY COUNT(`building`) DESC LIMIT 1)) t3
GROUP BY `name`, buildingcount
name | GROUP_CONCAT(`building`) | buildingcount
:---- | :----------------------- | ------------:
work1 | A1,A2 | 2
work2 | B1 | 3
work3 | A1 | 3
work4 | A1 | 5
work5 | A1 | 6
db<>fiddle here
Related
Media Table:
id
user_id
1
2
2
2
3
2
4
10
5
5
6
7
7
7
8
1
9
2
10
2
11
1
12
8
13
2
Seen Table:
id
user_id
media_id
friend_id
1
2
2
5
2
2
3
5
3
2
10
10
4
10
7
5
5
2
13
5
6
7
24
7
7
7
23
9
8
1
26
1
9
7
22
2
10
9
19
2
11
1
22
2
12
8
20
2
13
20
14
5
Result I want:
user_id
media_id
friend_id
2
1
NULL
2
2
5
2
3
5
2
9
NULL
2
10
NULL
2
13
5
My current query is this:
SELECT *
FROM media
LEFT JOIN seen ON seen.media_id=media.id
WHERE media.user_id = 2
UNION
SELECT *
FROM media
RIGHT JOIN seen ON seen.media_id=media.id
WHERE media.user_id = 2;
But this query is missing a condition for friend_id = 5 (I cannot figure this out).
Basically what I want to do is get all rows from Media Table where user_id = 2 and check friend_id = 5 from Seen Table for the specific user_id (2) and their media_id.
You can do this by only joing the tables once, but you need to psecify the on clause with the wanted ids
CREATE TABLE Media (
`id` INTEGER,
`user_id` INTEGER
);
INSERT INTO Media
(`id`, `user_id`)
VALUES
('1', '2'),
('2', '2'),
('3', '2'),
('4', '10'),
('5', '5'),
('6', '7'),
('7', '7'),
('8', '1'),
('9', '2'),
('10', '2'),
('11', '1'),
('12', '8'),
('13', '2');
CREATE TABLE Seen (
`id` INTEGER,
`user_id` INTEGER,
`media_id` INTEGER,
`friend_id` INTEGER
);
INSERT INTO Seen
(`id`, `user_id`, `media_id`, `friend_id`)
VALUES
('1', '2', '2', '5'),
('2', '2', '3', '5'),
('3', '2', '10', '10'),
('4', '10', '7', '5'),
('5', '2', '13', '5'),
('6', '7', '24', '7'),
('7', '7', '23', '9'),
('8', '1', '26', '1'),
('9', '7', '22', '2'),
('10', '9', '19', '2'),
('11', '1', '22', '2'),
('12', '8', '20', '2'),
('13', '20', '14', '5'),
('14','2','2', '4');
SELECT m.user_id, m.id as media_id, s.friend_id
FROM Media m LEFT JOIN Seen s ON s.user_id = m.user_id AND m.id = s.media_id AND s.friend_id = 5
WHERE m.user_id = 2
user_id | media_id | friend_id
------: | -------: | --------:
2 | 1 | null
2 | 2 | 5
2 | 3 | 5
2 | 9 | null
2 | 10 | null
2 | 13 | 5
db<>fiddle here
Please help me.
I have 2 table Users and Diseaselogs
1 user has many diseaselogs
I want to select all users and each user must be field date in diseaselogs is max
Data example
Users
id | name | age
1 | Nam | 21
2 | Thao | 23
3 | An | 19
Diseaselogs
id | logType | userId | date
1 | positive | 1 | 2021-06-21
2 | negative | 2 | 2021-06-22
3 | pending | 1 | 2021-06-24
4 | negative | 1 | 2021-06-26
5 | negative | 2 | 2021-06-21
6 | pending | 3 | 2021-06-23
7 | negative | 1 | 2021-06-24
8 | negative | 2 | 2021-06-25
9 | pending | 3 | 2021-06-28
Expect output
id | name | logId | logType | date
1 | Nam | 4 | negative | 2021-06-26
2 | Thao | 8 | negative | 2021-06-25
3 | An | 9 | pending | 2021-06-28
As ROW_NUMBER() doesn't support lower version of mysql i.e 5.7 to downwords. So I've tried here alternatives of ROW_NUMBER().
-- MySQL (V 5.6)
SELECT u.id, u.name, tmp.logId, tmp.logType, tmp.date
FROM users u
INNER JOIN (SELECT #row_no := IF(#prev_val = t.userId, #row_no + 1, 1) AS row_number
, #prev_val := t.userId AS userId
, t.date
, t.logType
, t.id AS logId
FROM Diseaselogs t,
(SELECT #row_no := 0) x,
(SELECT #prev_val := '') y
ORDER BY t.userId, t.date DESC ) tmp
ON u.id = tmp.userId
AND tmp.row_number = 1;
Please check url http://sqlfiddle.com/#!9/741b96/16
Also if your MySQL version is 5.8 then you can apply the below query where row_number() is used.
SELECT u.id, u.name, tmp.logId, tmp.logType, tmp.date
FROM users u
INNER JOIN (SELECT ROW_NUMBER() OVER (PARTITION BY userId ORDER BY date DESC) row_number
, userId
, date
, logType
, id AS logId
FROM Diseaselogs ) tmp
ON u.id = tmp.userId
AND tmp.row_number = 1;
in mysql 8 you can use ROW_NUMBER and an INNER JOIN
in prior versions you need to use another method for rownumber
Schema (MySQL v8.0)
CREATE TABLE Diseaselogs (
`id` INTEGER,
`logType` VARCHAR(8),
`userId` INTEGER,
`date` VARCHAR(10)
);
INSERT INTO Diseaselogs
(`id`, `logType`, `userId`, `date`)
VALUES
('1', 'positive', '1', '2021-06-21'),
('2', 'negative', '2', '2021-06-22'),
('3', 'pending', '1', '2021-06-24'),
('4', 'negative', '1', '2021-06-26'),
('5', 'negative', '2', '2021-06-21'),
('6', 'pending', '3', '2021-06-23'),
('7', 'negative', '1', '2021-06-24'),
('8', 'negative', '2', '2021-06-25'),
('9', 'pending', '3', '2021-06-28');
CREATE TABLE users (
`id` INTEGER,
`name` VARCHAR(4),
`age` INTEGER
);
INSERT INTO users
(`id`, `name`, `age`)
VALUES
('1', 'Nam', '21'),
('2', 'Thao', '23'),
('3', 'An', '19');
Query #1
SELECT
u.id, `name`, t1.id,`logType`, `date`
FROM
(SELECT
id,`logType`, `userId`, `date`
, ROW_NUMBER() OVER (PARTITION BY `userId` ORDER BY `date` DESC) rn
FROM
Diseaselogs) t1
INNER JOIN users u ON t1.userId = u.id
WHERE rn = 1;
id
name
id
logType
date
1
Nam
4
negative
2021-06-26
2
Thao
8
negative
2021-06-25
3
An
9
pending
2021-06-28
View on DB Fiddle
Schema (MySQL v8.0)
CREATE TABLE Diseaselogs (
`id` INTEGER,
`logType` VARCHAR(8),
`userId` INTEGER,
`date` VARCHAR(10)
);
INSERT INTO Diseaselogs
(`id`, `logType`, `userId`, `date`)
VALUES
('1', 'positive', '1', '2021-06-21'),
('2', 'negative', '2', '2021-06-22'),
('3', 'pending', '1', '2021-06-24'),
('4', 'negative', '1', '2021-06-26'),
('5', 'negative', '2', '2021-06-21'),
('6', 'pending', '3', '2021-06-23'),
('7', 'negative', '1', '2021-06-24'),
('8', 'negative', '2', '2021-06-25'),
('9', 'pending', '3', '2021-06-28');
CREATE TABLE users (
`id` INTEGER,
`name` VARCHAR(4),
`age` INTEGER
);
INSERT INTO users
(`id`, `name`, `age`)
VALUES
('1', 'Nam', '21'),
('2', 'Thao', '23'),
('3', 'An', '19');
Query #1
SELECT
u.id, `name`, `age`,`logType`, `date`
FROM
(SELECT
`logType`, `userId`, `date`
, ROW_NUMBER() OVER (PARTITION BY `userId` ORDER BY `date` DESC) rn
FROM
Diseaselogs) t1
INNER JOIN users u ON t1.userId = u.id
WHERE rn = 1;
id
name
age
logType
date
1
Nam
21
negative
2021-06-26
2
Thao
23
negative
2021-06-25
3
An
19
pending
2021-06-28
View on DB Fiddle
i have 2 tables (tbl_news and tbl_news_category)
tbl_news_category table is
cat_id cat_name general
1 name1 1
2 name2 1
3 name3 0
4 name4 1
5 name5 0
tbl_news table is
id cat_id title news_isimage
1 2 title1 1
2 5 title2 0
3 1 title2 1
4 3 title2 1
5 2 title2 1
6 5 title2 1
7 4 title2 1
8 5 title2 1
i want to get 5 random items from tbl_news which general value should be 1
i tried below code and its not working
SELECT
d.*
FROM
tbl_news d,
tbl_news_category p
WHERE
p.general = 1 AND d.news_isimage = 0
AND d.cat_id > 3
ORDER BY RAND()
LIMIT 5
but its giving news item with cat_id with general = 0
Do a proper join of the tables:
select n.*
from tbl_news n inner join tbl_news_category c
on c.cat_id = n.cat_id
where c.general = 1
order by rand() limit 5
You have also in your code the conditions:
news_isimage = 0 AND cat_id > 3
If you need them you can add them to the WHERE clause:
WHERE c.general = 1 AND n.news_isimage = 0 AND c.cat_id > 3
There is no data for your query available.
But do an INNER JOIN
CREATE TABLE tbl_news (
`id` INTEGER,
`cat_id` INTEGER,
`title` VARCHAR(6),
`news_isimage` INTEGER
);
INSERT INTO tbl_news
(`id`, `cat_id`, `title`, `news_isimage`)
VALUES
('1', '2', 'title1', '1'),
('2', '5', 'title2', '0'),
('3', '1', 'title2', '1'),
('4', '3', 'title2', '1'),
('5', '2', 'title2', '1'),
('6', '5', 'title2', '1'),
('7', '4', 'title2', '1'),
('8', '5', 'title2', '1');
CREATE TABLE tbl_news_category (
`cat_id` INTEGER,
`cat_name` VARCHAR(5),
`general` INTEGER
);
INSERT INTO tbl_news_category
(`cat_id`, `cat_name`, `general`)
VALUES
('1', 'name1', '1'),
('2', 'name2', '1'),
('3', 'name3', '0'),
('4', 'name4', '1'),
('5', 'name5', '0');
✓
✓
✓
✓
SELECT
tn.title
, tn.news_isimage
,tnc.cat_name
FROM tbl_news tn INNER JOIN tbl_news_category tnc ON tn.cat_id = tnc.cat_id
WHERE
tnc.general = 1
AND tn.news_isimage = 0
AND tnc.cat_id > 3
ORDER BY RAND()
LIMIT 5
title | news_isimage | cat_name
:---- | -----------: | :-------
db<>fiddle here
I have two tables, A and B, structured as follows.
CREATE TABLE TableA (
`id` INTEGER,
`code` VARCHAR(1),
`type` VARCHAR(1)
);
INSERT INTO TableA
(`id`, `code`, `type`)
VALUES
('1', 'A', 'r'),
('2', 'A', 'o'),
('3', 'A', 'u'),
('4', 'B', 'h');
CREATE TABLE TableB (
`id` INTEGER,
`sid` INTEGER,
`code` VARCHAR(1)
);
INSERT INTO TableB
(`id`, `sid`, `code`)
VALUES
('1', '1', 'A'),
('1', '1', 'A'),
('1', '1', 'A'),
('2', '1', 'B'),
('2', '1', 'B'),
('1', '2', 'A'),
('1', '2', 'A'),
('2', '2', 'A');
the output of this query should be like this
sid r o u
1 3 2 0
2 2 1 0
table A has a foreign key from table B which is the id. what I want to get is how many times each sid accessed each type of table A.
Left join Table B to Table A and aggregate:
select b.sid,
sum(a.type = 'r') r,
sum(a.type = 'o') o,
sum(a.type = 'u') u
from TableB b left join TableA a
on b.id = a.id
group by b.sid
See the demo.
Results:
| sid | r | o | u |
| --- | --- | --- | --- |
| 1 | 3 | 2 | 0 |
| 2 | 2 | 1 | 0 |
It seems like I can either count sales and events ("COUNT(DISTINCT event) as SaleCount" in the event-sale join temp table) in a waiter-month or count the number of event attendees served in a waiter-month (in the event table), but not both in the same SQL statement unless I use iteration (which I am trying to avoid as I am scared of the loop overhead)
Events table
CREATE TABLE events (
`event` INTEGER,
`month` VARCHAR(3),
`attendees` INTEGER,
`waiter` VARCHAR(3)
);
INSERT INTO
events
(`event`, `month`, `attendees`, `waiter`) VALUES
('1', 'jan', '5', 'bob'),
('2', 'feb', '2', 'bob'),
('3', 'feb', '1', 'bob'),
('4', 'feb', '2', 'sally');
Sales table
CREATE TABLE sales (
`sale` INTEGER,
`event` INTEGER,
`profit` INTEGER
);
INSERT INTO
sales
(`sale`, `event`, `profit`) VALUES
('1', '1', '10'),
('2', '1', '20'),
('3', '1', '15'),
('4', '2', '25'),
('5', '2', '5'),
('6', '2', '30'),
('7', '3', '25'),
('8', '3', '5'),
('9', '3', '30'),
('10', '4', '25'),
('11', '4', '5'),
('12', '4', '30');
Event-Sales join temp table
sale event month attendees profit ($) waiter
1 1 jan 5 10 bob
2 1 jan 5 20 bob
3 1 jan 5 15 bob
4 2 feb 2 25 bob
5 2 feb 2 5 bob
6 2 feb 2 30 bob
7 3 feb 1 25 bob
8 3 feb 1 5 bob
9 3 feb 1 30 bob
10 4 feb 2 25 sally
11 4 feb 2 5 sally
12 4 feb 2 30 sally
Required output
Productivity for month
waiter-month attendees events sales
bob-jan 5 1 3
bob-feb 3 2 6
sally-feb 2 1 3
Edit:
Above I only now added "waiter", "waiter-month" and replaced sale count with event count as i forgot this is in fact the requirement
It's also possible to join 2 sub-queries.
select
concat(qe.waiter,'-',qe.month) as `waiter-month`
, qe.attendees
, qe.events
, qs.sales
from
(
select e.waiter, e.month
, month(str_to_date(e.month,'%b')) as monthNr
, sum(attendees) as attendees
, count(*) as events
from events e
group by e.month, e.waiter
) qe
left join
(
select e.month, e.waiter
, sum(s.profit) as profits
, count(s.sale) as sales
from events e
join sales s
on s.event = e.event
group by e.month, e.waiter
) qs
on qs.month = qe.month
and qs.waiter = qe.waiter
order by qe.waiter, qe.monthNr
waiter-month | attendees | events | sales
:----------- | --------: | -----: | ----:
bob-jan | 5 | 1 | 3
bob-feb | 3 | 2 | 6
sally-feb | 2 | 1 | 3
db<>fiddle here
Unless I'm missing something, this seems like a straightforward GROUP BY using COUNT(DISTINCT) and SUM():
SELECT
e.event as EventId,
COUNT(DISTINCT s.sales) as SaleCount,
SUM(e.attendees) as TotalAttendees
FROM event e
JOIN sales s
ON e.event = s.event
GROUP BY e.event
You can group by event, month:
select
s.event, e.month,
max(e.attendees) attendees,
count(s.profit) sales
from sales s inner join events e
on e.event = s.event
group by s.event, e.month
See the demo.
Results:
> event | month | attendees | sales
> ----: | :---- | --------: | ----:
> 1 | jan | 5 | 3
> 2 | feb | 2 | 3
Or group by month only:
select
e.month,
max(e.attendees) attendees,
count(s.profit) sales
from sales s inner join events e
on e.event = s.event
group by e.month