Query to display row after 1 pm - mysql

How to fetch all rows from table where time is greater than 13:00 i.e. 1PM
SELECT * FROM `mytable` WHERE `time` >="13:00";

if you have a datetime field you could do this (I'm assuming here as you haven't specified):
create table tester(`id` int(6), `name` varchar(50), `datetest` datetime);
insert into tester(`id`,`name`,`datetest`)
values(1, 'n1', '2018-12-20 09:00:00'),
(2, 'n2', '2018-12-20 10:00:00'),
(3, 'n3', '2018-12-20 13:10:00'),
(4, 'n4', '2018-12-20 14:00:00');
select * from tester
where TIME(datetest) > '13:00'

Related

Lead window function in mysql to find sales

Given this table. I would like to know for each day how many different customers made a sale on date t and and t+1.
-- create a table
CREATE TABLE sales_t(
id INTEGER PRIMARY KEY,
d_date date NOT NULL,
sale INT NOT NULL,
customer_n INT NOT NULL
);
-- insert some values
INSERT INTO sales_t VALUES (1, '2021-06-30', 12, 1);
INSERT INTO sales_t VALUES (2, '2021-06-30', 22, 5);
INSERT INTO sales_t VALUES (3, '2021-06-30', 111, 3);
INSERT INTO sales_t VALUES (4, '2021-07-01', 27, 1);
INSERT INTO sales_t VALUES (5, '2021-07-01', 90, 4);
INSERT INTO sales_t VALUES (6, '2021-07-01', 33, 3);
INSERT INTO sales_t VALUES (6, '2021-07-01', 332, 3);
The result for date 2021-06-30 is 2 because customer 1 and 3 made a sale in t and t+1.
Date sale_t_and_t+1
.....................................
2021-06-30 2
2021-07-01 0
Use LEAD() window function for each distinct combination of date and customer to create a flag which will be 1 if the customer is present in both days or 0 if not and aggregate:
SELECT d_date, COALESCE(SUM(flag), 0) `sale_t_and_t+1`
FROM (
SELECT DISTINCT d_date, customer_n,
LEAD(d_date) OVER (PARTITION BY customer_n ORDER BY d_date) = d_date + INTERVAL 1 DAY flag
FROM sales_t
) t
GROUP BY d_date;
See the demo.

SQL to count staff working at time with join

I am new to SQL.
I want to count staff working at a particular time.
The data schema has a Person table and a Shifts table. They are joined by a StaffShifts table which has both a user_id field and a shift_id field.
Each staff member can have many shifts, and each shift can have many staff.
create table Person
(
user_id INT,
rank_id INT,
groupschedule_id INT,
personnum VARCHAR(6),
PRIMARY KEY (user_id)
);
INSERT INTO Person (user_id, rank_id, groupschedule_id, personnum)
VALUES
(1, 1, 1, 'ABC123'),
(2, 1, 2, 'DEF456'),
(3, 2, 3, 'GHI789'),
(4, 1, 1, 'JKL123'),
(5, 3, 2, 'NOP123'),
(6, 1, 3, 'RST789'),
(7, 2, 1, 'WXY789'),
(8, 1, 2, 'ABC432'),
(9, 1, 3, 'DEF789')
;
CREATE TABLE Groupschedule
(
groupschedule_id INT,
shortnm char(20)
);
INSERT INTO Groupschedule
VALUES
(1,'TEAM 1'),
(2,'TEAM 2'),
(3,'TEAM 3')
;
CREATE TABLE Shifts
(
shift_id INT PRIMARY KEY,
shift_start datetime,
shift_end datetime
);
INSERT INTO Shifts
VALUES
(1, '2021-03-08 06:45:00', '2021-03-08 15:00:00'),
(2, '2021-03-08 14:00:00', '2021-03-08 23:00:00'),
(3, '2021-03-08 23:00:00', '2021-04-09 07:00:00')
;
CREATE TABLE Osl
(
shift_id INT,
osl INT,
area char(10),
FOREIGN KEY (shift_id) REFERENCES Shifts(shift_id)
);
INSERT INTO Osl
VALUES
(1,3, 'EAST'),
(2,2, 'EAST'),
(3,2, 'EAST')
;
CREATE TABLE StaffShifts
( shift_id INT,
user_id INT,
FOREIGN KEY (shift_id) REFERENCES Shifts(shift_id),
FOREIGN KEY (user_id) REFERENCES Person(user_id)
);
WHATS BEEN TRIED
I tried to start with retrieving all the staff working at the time with:
SELECT shift_id FROM Shifts WHERE shift_start < '2021-03-08 11:00:00' AND shift_end > '2021-03-08 11:00:00'
INNER JOIN StaffShifts ON Person.user_id=StaffShifts.user_id
On a fiddle this results in an error that references the INNER JOIN but does not elaborate.
I have created a fiddle here https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=1572ed28005766d30a18521557aadb90
UPDATE
I have tried SQL statement:
SELECT shift_id FROM Shifts INNER JOIN StaffShifts ON Person.user_id=StaffShifts.user_id
WHERE shift_start < '2021-03-08 11:00:00' AND shift_end > '2021-03-08 11:00:00'
However this produces and error shift_id is ambiguous.
UPDATE
Since i really want to COUNT the users working a given shift I am trying to return a list of users - using JOINs for the two one to many relationships:
SELECT Person.user_id
FROM Person
INNER JOIN StaffShifts ON Person.user_id=StaffShifts.user_id
INNER JOIN StaffShifts ON Shifts.shift_id=StaffShifts.shift_id
WHERE Shifts.shift_start < '2021-03-08 11:00:00'
AND Shifts.shift_end > '2021-03-08 11:00:00'
But this results in 'Not unique table/alias: 'StaffShifts''
Note I have not tried to use COUNT until I return a list of Persons.
You need to include Person - which you want to count, StaffShifts - where a person is assigned to a shift so you could also join Shifts based on that, and Shifts - where you check the hour range you wish.
SELECT
COUNT(*)
FROM `Person`
INNER JOIN `StaffShifts` ON `Person`.`user_id` = `StaffShifts`.`user_id`
INNER JOIN `Shifts` ON `StaffShifts`.`shift_id` = `Shifts`.`shift_id`
WHERE
Shifts.shift_start < '2021-03-08 11:00:00'
AND Shifts.shift_end > '2021-03-08 14:00:00'
;

sql select from table with date range condition

I have this table
CREATE TABLE `tarif` (
`tarif_id` int(11) NOT NULL AUTO_INCREMENT,
`start_tarif` date NOT NULL,
`end_tarif` date NOT NULL,
`day_tarif` varchar(50) NOT NULL,
PRIMARY KEY (`tarif_id`)
);
INSERT INTO `tarif` VALUES (1, '2019-02-01', '2019-02-10', '10'),
(2, '2019-02-11', '2019-02-20', '20'),
(3, '2019-02-21', '2019-02-28', '10'),
(4, '2019-03-01', '2019-02-10', '15');
How can I get day_tarif between 2019-02-05 and 2019-02-15 and calculate the sum = day_tarif * number of date betwwen 2019-02-05 and 2019-02-15
You can use the following solution using DATEDIFF:
SELECT SUM((DATEDIFF(LEAST(`end_tarif`, '2019-02-15'), GREATEST(`start_tarif`, '2019-02-05')) + 1) * `day_tarif`) AS sumCustom
FROM `tarif`
WHERE `end_tarif` >= '2019-02-05' AND `start_tarif` <= '2019-02-15'
demo on dbfiddle.uk
You can use the following solution using SUM and COUNT:
SELECT SUM(`day_tarif`) * COUNT(`tarif_id`)
FROM `tarif`
WHERE `end_tarif` >= '2019-02-05' AND `start_tarif` <= '2019-02-15'
select SUM(day_tarif) * COUNT(tarif_id)
from tarif
where end_date >= '2019-02-05' AND start_date <= '2019-02-15'
This question has been asked several times, or something like it. Be sure to search StackOverflow before asking a duplicate: SQL query to select dates between two dates
You can try following code:
WITH cte AS(
SELECT *
FROM tablename
WHERE end_tarif >= '2019-02-05' AND start_tarif <= '2019-02-15'
)
SELECT day_tarif, day_tarif * COUNT(tarif_id) AS 'SUM'
FROM cte
group by day_tarif;
I think this might be what you are after...
Declare #tarif as table (
tarif_id int NOT NULL ,
start_tarif date NOT NULL,
end_tarif date NOT NULL,
day_tarif varchar(50) NOT NULL
);
INSERT INTO #tarif VALUES (1, '2019-02-01', '2019-02-10', '10'),
(2, '2019-02-11', '2019-02-20', '20'),
(3, '2019-02-21', '2019-02-28', '10'),
(4, '2019-03-01', '2019-02-10', '15');
-- Declare parameters
Declare #paramstart date, #paramend date
Set #paramstart='2019-02-05'
Set #paramend='2019-02-15'
-- Set up loop
Declare #mincount int, #maxcount int, #myval int, #curstart date, #curend date,#curtarif int, #mytarif int
Set #mincount=(Select MIN(tarif_id) from #tarif where end_tarif >= '2019-02-05' AND start_tarif <= '2019-02-15')
Set #maxcount=(Select Max(tarif_id) from #tarif where end_tarif >= '2019-02-05' AND start_tarif <= '2019-02-15')
Set #mytarif=0
-- Do loop
WHile #mincount<=#maxcount
BEGIN
Set #curstart=(Select start_tarif from #tarif where tarif_id=#mincount)
Set #curend=(Select end_tarif from #tarif where tarif_id=#mincount)
Set #curtarif=(Select cast(day_tarif as int) from #tarif where tarif_id=#mincount)
IF #paramstart between #curstart and #curend
BEGIN
Set #mytarif=#mytarif+((DATEDIFF(day,#paramstart,#curend)+1) * #curtarif)
END
IF #paramend between #curstart and #curend
BEGIN
Set #mytarif=#mytarif+((DATEDIFF(day,#curstart,#paramend)+1) * #curtarif)
END
IF #paramstart not between #curstart and #curend and #paramend not between #curstart and #curend
BEGIN
Set #mytarif=#mytarif+((DATEDIFF(day,#curstart,#curend)+1) * #curtarif)
END
Set #mincount=#mincount+1
END
Select #mytarif as tarif
Try this!
select day_tarif , sum(day_tarif * count (*)) as sum
where start_tarif between '2019/02/05' and '2019/02/15' and end_tarif between '2019/02/05' and '2019/02/15'
group by day_tarif;

MySQL: Select first row with value in interval

With the following table:
CREATE TABLE table1 (`id` INT, `num` INT);
INSERT INTO table1 (`id`, `num`) VALUES
(1, 1),
(1, 5),
(1, 7),
(1, 12),
(1, 22),
(1, 23),
(1, 24),
(2, 1),
(2, 6);
How do I select a row for each num interval of 5 (ie. select the first row for [0,5), the first for [5,10), the first for [10,15), etc.), with a given id? Is this possible with a MySQL query, or must I process it in a programming language later?
For reference, the output I'd want for id=1:
(1, 1), (1,5), (1,12), (1,22)
Here is a short query:
select min(num), ceiling((num + 1)/5)
from table1
where id = 1
group by ceiling((num + 1)/5);

SQL getting shifts outside of availability

I'm trying to put together an sql query to get employee shifts that are outside of their availability for a scheduling app. Availability entries will be contiguous and will never have availability entries that are back-to-back for the same employee, nor will there be availability entries that overlap for the same employee.
Basically, I need to get the shift rows where (availabilities.start <= shifts.start AND availabilities.end >= shifts.end) does NOT hold true. Phrased another way, I need to get the rows from the shifts table that are not fully contained by an availability entry.
It needs to account for these possibilities:
Shifts that start before availability
Shifts that end after availability
Shifts that do not have any availability during the shift
I'm ok with using a stored procedure instead of a query if this would be more efficient.
Here's what the tables look like:
CREATE TABLE availabilities (`id` int primary key, `employee_id` int, `start` datetime, `end` datetime);
CREATE TABLE shifts (`id` int primary key, `employee_id` int, `start` datetime, `end` datetime);
Here is some sample data:
INSERT INTO availabilities
(`employee_id`, `start`, `end`)
VALUES
(1, '2015-01-01 08:00:00', '2015-01-01 09:00:00'),
(1, '2015-01-02 08:00:00', '2015-01-02 10:00:00'),
(2, '2015-01-03 08:00:00', '2015-01-03 14:00:00'),
(2, '2015-01-04 08:00:00', '2015-01-04 18:00:00')
;
INSERT INTO shifts
(`employee_id`, `start`, `end`)
VALUES
(1, '2015-01-01 08:00:00', '2015-01-01 09:00:00'),
(1, '2015-01-02 08:30:00', '2015-01-02 10:00:00'),
(1, '2015-01-02 10:30:00', '2015-01-02 12:00:00'),
(2, '2015-01-03 08:00:00', '2015-01-03 09:00:00'),
(2, '2015-01-03 09:00:00', '2015-01-03 14:30:00'),
(2, '2015-01-04 09:30:00', '2015-01-04 17:30:00'),
(2, '2015-01-05 08:00:00', '2015-01-05 10:00:00')
;
I would expect the 3rd, 5th and 7th shifts to be output as they are outside of availability.
I've tried something like the following (as well as many others) however all of them either give false positives or leave out shifts.
SELECT s.* FROM `shifts` AS `s`
LEFT JOIN `availabilities` AS `a` ON `s`.`employee_id` = `a`.`employee_id`
WHERE (NOT(a.start <= s.start AND a.end >= s.end) OR a.id IS NULL);
Does this help?
select *
from shifts as s
where not exists (
select 1
from availabilities as a
where a.start <= s.start AND a.end >= s.end and a.employee_id = s.employee_id
)