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
Let's say I have the following table:
id
engine_id
timestamp
engine_is_on
13
1
1015
1
12
1
1010
1
11
1
1008
0
10
1
1006
1
9
2
1005
1
8
1
1005
1
7
2
1004
1
6
1
1004
1
5
1
1003
0
4
2
1002
0
3
1
1002
1
2
2
1001
1
1
1
1001
1
How to get the first and last id of entries grouped by the alternating column engine_is_on and also grouped by engine_id? Maybe an example of the desired result can clearify what I mean:
engine_id
start_id
end_id
1
13
12
1
10
6
2
9
7
1
3
1
2
2
2
Just for clarity's sake: for each appearance of engine_is_on being 0 a new row is being created for the engine_id.
SQL to reproduce:
CREATE TABLE mytable(
`id` INT(11) AUTO_INCREMENT PRIMARY KEY,
`engine_id` INT(11),
`timestamp` INT(11),
`engine_is_on` TINYINT(1)
);
INSERT INTO mytable(`engine_id`, `timestamp`, `engine_is_on`) VALUES
('1', '1001', '1'),
('2', '1001', '1'),
('1', '1002', '1'),
('2', '1002', '0'),
('1', '1003', '0'),
('1', '1004', '1'),
('2', '1004', '1'),
('1', '1005', '1'),
('2', '1005', '1'),
('1', '1006', '1'),
('1', '1008', '0'),
('1', '1010', '1'),
('1', '1015', '1');
SELECT * FROM mytable ORDER BY id DESC;
I know that I am expected to provide what I tried, but I don't even know where to start. Or how to google correctly to guide me in the right direction.
Feel free to comment on how to make this question more understandable (including setting a proper title)
You can sum the values where engine_is_on is 0 then filter and aggregation:
select engine_id, min(id), max(id)
from (select mytable.*,
sum(engine_is_on = 0) over (partition by engine_id order by timestamp) as grp
from mytable
) t
where engine_is_on = 1
group by engine_id, grp;
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 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
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 |