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;
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
Take an example of a table (tblabc) with the following data
id amount
1 10
2 20
3 50
4 30
5 90
6 80
7 70
8 40
9 100
10 60
Normally, if you apply the code SELECT * FROM tblabc ORDER BY `amount` DESC LIMIT 0,2 it will return its result based on the first 2 columns only, which is not my desired result
What it will return
id amount
1 20
2 10
You can clearly see that the result is only from the first 2 columns instead of the whole table, sorted.
My desired result would be:
id amount
9 100
5 90
Also how the method applied should be consistent with the pagination i.e at the second phase SELECT * FROM tblabc ORDER BY `amount` DESC LIMIT 2,2 it should produce
id amount
6 80
7 70
Your desired results are wrong.
But you need only to order it by amount DESC
CREATE TABLE table1 (
`id` INTEGER,
`amount` INTEGER
);
INSERT INTO table1
(`id`, `amount`)
VALUES
('1', '10'),
('2', '20'),
('3', '50'),
('4', '30'),
('5', '90'),
('6', '80'),
('7', '70'),
('8', '40'),
('9', '100'),
('10', '60');
SELECT * FROM table1 ORDER BY `amount` DESC LIMIT 0,2
id | amount
-: | -----:
9 | 100
5 | 90
SELECT * FROM table1 ORDER BY `amount` DESC LIMIT 2,2
id | amount
-: | -----:
6 | 80
7 | 70
db<>fiddle here
The query should be “select * from tableabc ORDER BY amount” not just BY. That wouldnt even work in MySQL.
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
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