I am trying to do an insert select but require some aliased values for calculations but don't need all of them for my insert. I just need field0, total_sum, hard_coded_val but rely on the others for the calculations.
is there any way to either ignore the other values or specify the VALUES() in the insert SELECT?
INSERT INTO table(field0,total_sum,hard_coded_val)
SELECT s.*, sum1+sum2 AS total_sum, 'hard_coded_val' FROM
(SELECT t.*, (fielda+fieldb)*2 AS sum1, (fieldc+fieldd)/4 AS sum2 from
(SELECT field0,
sum(IF(field1 = 1, totalcount,0)) AS fielda,
sum(IF(field1 = 2, totalcount,0)) AS fieldb,
sum(IF(field1 = 3, totalcount,0)) AS fieldc,
sum(IF(field1 = 4,totalcount,0)) AS fieldd
from source_table GROUP BY field0)
t ORDER BY sum1 DESC)
s ORDER BY total_sum DESC
You just need to limit the number of columns you're returning. * will return all columns for the table associated with it.
INSERT INTO table(field0,total_sum,hard_coded_val)
SELECT s.field0, sum1+sum2 AS total_sum, 'hard_coded_val' FROM
...
I have the following columns in a table called meetings: meeting_id - int, start_time - time, end_time - time. Assuming that this table has data for one calendar day only, how many minimum number of rooms do I need to accomodate all the meetings. Room size/number of people attending the meetings don't matter.
Here's the solution:
select * from
(select t.start_time,
t.end_time,
count(*) - 1 overlapping_meetings,
count(*) minimum_rooms_required,
group_concat(distinct concat(y.start_time,' to ',t.end_time)
separator ' // ') meeting_details from
(select 1 meeting_id, '08:00' start_time, '09:15' end_time union all
select 2, '13:20', '15:20' union all
select 3, '10:00', '14:00' union all
select 4, '13:55', '16:25' union all
select 5, '14:00', '17:45' union all
select 6, '14:05', '17:45') t left join
(select 1 meeting_id, '08:00' start_time, '09:15' end_time union all
select 2, '13:20', '15:20' union all
select 3, '10:00', '14:00' union all
select 4, '13:55', '16:25' union all
select 5, '14:00', '17:45' union all
select 6, '14:05', '17:45') y
on t.start_time between y.start_time and y.end_time
group by start_time, end_time) z;
My question - is there anything wrong with this answer? Even if there's nothing wrong with this, can someone share a better answer?
Let's say you have a table called 'meeting' like this -
Then You can use this query to get the minimum number of meeting Rooms required to accommodate all Meetings.
select max(minimum_rooms_required)
from (select count(*) minimum_rooms_required
from meetings t
left join meetings y on t.start_time >= y.start_time and t.start_time < y.end_time group by t.id
) z;
This looks clearer and simple and works fine.
Meetings can "overlap". So, GROUP BY start_time, end_time can't figure this out.
Not every algorithm can be done in SQL. Or, at least, it may be grossly inefficient.
I would use a real programming language for the computation, leaving the database for what it is good at -- being a data repository.
Build a array of 1440 (minutes in a day) entries; initialize to 0.
Foreach meeting:
Foreach minute in the meeting (excluding last minute):
increment element in array.
Find the largest element in the array -- the number of rooms needed.
CREATE TABLE [dbo].[Meetings](
[id] [int] NOT NULL,
[Starttime] [time](7) NOT NULL,
[EndTime] [time](7) NOT NULL) ON [PRIMARY] )GO
sample data set:
INSERT INTO Meetings VALUES (1,'8:00','09:00')
INSERT INTO Meetings VALUES (2,'8:00','10:00')
INSERT INTO Meetings VALUES (3,'10:00','11:00')
INSERT INTO Meetings VALUES (4,'11:00','12:00')
INSERT INTO Meetings VALUES (5,'11:00','13:00')
INSERT INTO Meetings VALUES (6,'13:00','14:00')
INSERT INTO Meetings VALUES (7,'13:00','15:00')
To Find Minimum number of rooms required run the below query:
create table #TempMeeting
(
id int,Starttime time,EndTime time,MeetingRoomNo int,Rownumber int
)
insert into #TempMeeting select id, Starttime,EndTime,0 as MeetingRoomNo,ROW_NUMBER()
over (order by starttime asc) as Rownumber from Meetings
declare #RowCounter int
select top 1 #RowCounter=Rownumber from #TempMeeting order by Rownumber
WHILE #RowCounter<=(Select count(*) from #TempMeeting)
BEGIN
update #TempMeeting set MeetingRoomNo=1
where Rownumber=(select top 1 Rownumber from #TempMeeting where
Rownumber>#RowCounter and Starttime>=(select top 1 EndTime from #TempMeeting
where Rownumber=#RowCounter)and MeetingRoomNo=0)set #RowCounter=#RowCounter+1
END
select count(*) from #TempMeeting where MeetingRoomNo=0
Consider a table meetings with columns id, start_time and end_time. Then the following query should give correct answer.
with mod_meetings as (select id, to_timestamp(start_time, 'HH24:MI')::TIME as start_time,
to_timestamp(end_time, 'HH24:MI')::TIME as end_time from meetings)
select CASE when max(a_cnt)>1 then max(a_cnt)+1
when max(a_cnt)=1 and max(b_cnt)=1 then 2 else 1 end as rooms
from
(select count(*) as a_cnt, a.id, count(b.id) as b_cnt from mod_meetings a left join mod_meetings b
on a.start_time>b.start_time and a.start_time<b.end_time group by a.id) join_table;
Sample DATA:
DROP TABLE IF EXISTS meeting;
CREATE TABLE "meeting" (
"meeting_id" INTEGER NOT NULL UNIQUE,
"start_time" TEXT NOT NULL,
"end_time" TEXT NOT NULL,
PRIMARY KEY("meeting_id")
);
INSERT INTO meeting values (1,'08:00','14:00');
INSERT INTO meeting values (2,'09:00','10:30');
INSERT INTO meeting values (3,'11:00','12:00');
INSERT INTO meeting values (4,'12:00','13:00');
INSERT INTO meeting values (5,'10:15','11:00');
INSERT INTO meeting values (6,'12:00','13:00');
INSERT INTO meeting values (7,'10:00','10:30');
INSERT INTO meeting values (8,'11:00','13:00');
INSERT INTO meeting values (9,'11:00','14:00');
INSERT INTO meeting values (10,'12:00','14:00');
INSERT INTO meeting values (11,'10:00','14:00');
INSERT INTO meeting values (12,'12:00','14:00');
INSERT INTO meeting values (13,'10:00','14:00');
INSERT INTO meeting values (14,'13:00','14:00');
Solution:
DROP VIEW IF EXISTS Final;
CREATE VIEW Final AS SELECT time, group_concat(event), sum(num) num from (
select start_time time, 's' event, 1 num from meeting
union all
select end_time time, 'e' event, -1 num from meeting)
group by 1
order by 1;
select max(room) AS Min_Rooms_Required FROM (
select
a.time,
sum(b.num) as room
from
Final a
, Final b
where a.time >= b.time
group by a.time
order by a.time
);
Here's the explanation to gashu's nicely working code (or otherwise a non-code explanation of how to solve it with any language).
Firstly, if the variable 'minimum_rooms_required' would be renamed to 'overlap' it would make the whole thing much easier to understand. Because for each of the start or end times we want to know the numbers of overlapping ongoing meetings. When we found the maximum, this means there's no way of getting around with less than the overlapping amount, because well they overlap.
By the way, I think there might be a mistake in the code. It should check for t.start_time or t.end_time between y.start_time and y.end_time. Counterexample: meeting 1 starts at 8:00, ends at 11:00 and meeting 2 starts at 10:00, ends at 12:00.
(I'd post it as a comment to the gashu's answerbut I don't have enough reputation)
I'd go for Lead() analytic function
select
sum(needs_room_ind) as min_rooms
from (
select
id,
start_time,
end_time,
case when lead(start_time,1) over (order by start_time asc) between start_time
and end_time then 1 else 0 end as needs_room_ind
from
meetings
) a
IMO, I wanna to take the difference between how many meeting are started and ended at the same time when each meeting_id is started (assuming meeting starts and ends on time)
my code was just like this :
with alpha as
(
select a.meeting_id,a.start_time,
count(distinct b.meeting_id) ttl_meeting_start_before,
count(distinct c.meeting_id) ttl_meeting_end_before
from meeting a
left join
(
select meeting_id,start_time from meeting
) b
on a.start_time > b.start_time
left join
(
select meeting_id,end_time from meeting
) c
on a.start_time > c.end_time
group by a.meeting_id,a.start_time
)
select max(ttl_meeting_start_before-ttl_meeting_end_before) max_meeting_room
from alpha
I have one table and i want to check that for one column all value are same.
following is the entry in my table.
two column
rid,value
(1,1)
(1,1)
(2,1)
(2,0)
(2,0)
(3,0)
(3,0)
(3,0)
I want query which gives me rid 1 because all of its value is 1. all record for rid 1 has value 1 and rid 2 and 3 does not has all value as 1 so they should not be selected.
Using group by and having can get what you want:
SELECT rid, value
FROM my_table
GROUP BY rid
HAVING COUNT( distinct value) = 1
UPDATE
According to the comment, filter the value will get the result:
SELECT *
FROM
(
SELECT rid, value
FROM my_table
GROUP BY rid
HAVING COUNT( distinct value) = 1
) AS T1
WHERE value = 1
If the values would only be 1 or 0, then you could do this trick:
SELECT rid, value
FROM my_table
GROUP BY rid
HAVING COUNT( * ) = SUM(value)
You can do like this:
CREATE TABLE my_table (
id varchar(255),
col_value varchar(255)
);
INSERT INTO my_table
VALUES
('1','1'),
('1','1'),
('2','1'),
('2','1'),
('2','1'),
('2','4'),
('3','1'),
('3','1');
Query for selection:
SELECT src.* FROM
(
SELECT DISTINCT t1.* FROM my_table AS t1
) AS src
WHERE src.id NOT IN(
SELECT test.id
FROM
(
SELECT DISTINCT t1.* FROM my_table AS t1
) AS test
GROUP BY test.id
HAVING COUNT(*) > 1
)
fiddle here.
I m working on sql server and stucked with how can I get the desired output.
I have the below as the source table.
and I want the desired output as below.
Here is the Query to have source table.
DECLARE #Temp TABLE(Capacity INT,CDate DATE,Name NVARCHAR(100))
INSERT INTO #Temp VALUES (1,'4/14/2014','M24')
INSERT INTO #Temp VALUES (1,'4/15/2014','M22')
INSERT INTO #Temp VALUES (1,'4/14/2014','M24')
INSERT INTO #Temp VALUES (1,'4/15/2014',NULL)
INSERT INTO #Temp VALUES (2,'4/14/2014','F67')
INSERT INTO #Temp VALUES (2,'4/15/2014','F31')
INSERT INTO #Temp VALUES (3,'4/14/2014','M53')
SELECT * FROM #Temp
Can anyone help me, please.
You can use the PIVOT function to get the result but since you need to return multiple rows for each Capacity, you will want to use a windowing function like row_number() that will generate a unique sequence for each Capacity and CDate combination:
SELECT Capacity, [2014-04-14], [2014-04-15]
FROM
(
SELECT Capacity,
CDate,
Name,
row_number() over(partition by capacity, cdate
order by capacity) seq
FROM #Temp
) d
PIVOT
(
MAX(name)
FOR CDate IN ([2014-04-14], [2014-04-15])
) piv
ORDER BY Capacity;
See SQL Fiddle with Demo
Let suppose my table can have values from 000 to 999 (three digits and less than 1000)
Some of this values are filled. Let's suppose currently my table has
000,002,005,190 (001,004,003,006,..189,191,..,999 can be inserted into table)
and these values are randomly allocated 000 and 002 is in table but 001 is not in table yet.
How can I get the values that I can insert into table yet.
DECLARE #t TABLE
(VALUE CHAR(3))
INSERT #t
VALUES
('000'),('002'),('005'),('190')
;WITH rnCTE
AS
(
SELECT -1 + ROW_NUMBER() OVER (ORDER BY TYPE, number, name) AS rn
FROM master.dbo.spt_values
)
SELECT RIGHT('000' + CAST( rn AS VARCHAR(11)),3)
FROM rnCTE
WHERE NOT EXISTS ( SELECT 1 FROM #t
WHERE VALUE = rn
)
AND rn < 1000
EDIT
This query works by generating the complete list of possible numbers from a system table (master.dbo.spt_values) which is guaranteed to contain more than 1000 rows inside the CTE rnCTE. -1 is added to ROW_NUMBER to have the values start at 0 rather than 1.
The outer query zero pads the numbers for display, returning only those which are not in the source data and are less than 1000.
DECLARE #t TABLE(id INT)
INSERT INTO #t (id)
VALUES
(1),(19),(3)
;WITH numbers AS (
SELECT ROW_NUMBER() OVER(ORDER BY o.object_id,o2.object_id) RN FROM sys.objects o
CROSS JOIN sys.objects o2
), NotExisted AS(
SELECT * FROM numbers WHERE RN NOT IN (SELECT ID FROM #t)
AND RN<1000)
SELECT TOP 1 RN FROM NotExisted ORDER BY NEWID()
You will have to write a T-SQL to first query and find the gaps. There is no ready made SQL that will give you the gaps directly.