Output elements between specific element - sql

Suppose I have a table with a column which looks like:
SELECT Col1
FROM table;
Col1
A
A
B
B
C
C
D
B
E
B
F
I would like to output elements that are between "B"s, which are C, D, E
How can I do that with a query?

declare #t table (ID INT IDENTITY(1,1),col1 VARCHAR(10))
insert into #t (col1) values ('A')
insert into #t (col1) values ('A')
insert into #t (col1) values ('B')
insert into #t (col1) values ('B')
insert into #t (col1) values ('C')
insert into #t (col1) values ('C')
insert into #t (col1) values ('B')
insert into #t (col1) values ('E')
insert into #t (col1) values ('B')
insert into #t (col1) values ('F')
select ID,col1 from #t
where ID between (select MIN(id) from #t WHERE col1 = 'B') and
(select MAX(id) from #t WHERE col1 = 'B')
and col1<>'B'

Related

Update query in oracle sql

create table table1(accountno number);
insert into table1 values (1);
insert into table1 values (2);
insert into table1 values (3);
insert into table1 values (4);
insert into table1 values (5);
insert into table1 values (6);
create table table2(accountno number,check_y_n varchar2(20));
insert into table2 (accountno) values (4);
insert into table2 (accountno) values (5);
insert into table2 (accountno) values (6);
insert into table2 (accountno) values (7);
insert into table2 (accountno) values (8);
insert into table2 (accountno) values (9);
I need below two update query in single query using joins. Can anyone help me on this
UPDATE TABLE2 SET check_y_n ='YES' WHERE accountno IN (SELECT accountno FROM TABLE1);
UPDATE TABLE2 SET check_y_n ='NO' WHERE accountno NOT IN (SELECT accountno FROM TABLE1);
Use a CASE expression:
UPDATE TABLE2
SET check_y_n = CASE
WHEN accountno IN (SELECT accountno FROM TABLE1)
THEN 'YES'
ELSE 'NO'
END;
db<>fiddle here

Removing count column from query output

select top (5) t3.Model, t3.Manufacturer, t1.Colour, t1.RegistrationNumber, t1.DailyRentalPrice, count(t2.TruckID) as RentedAmount
from [IndividualTruck-PB] t1
inner join [TruckRental-PB] t2 on t1.TruckID = t2.TruckID
inner join [TruckModel-PB] t3 on t1.TruckModelID = t3.ModelID
group by t3.Model, t3.Manufacturer, t1.Colour, t1.RegistrationNumber, t1.DailyRentalPrice
order by RentedAmount desc
Bsically, I'm trying to get the top 5 most rented but don't want the actual count column as output only as a means of ordering the output. Is this possible?
You can try remove the count column and give the formula to order by part:
select top (5) t3.Model, t3.Manufacturer, t1.Colour, t1.RegistrationNumber, t1.DailyRentalPrice
from [IndividualTruck-PB] t1
inner join [TruckRental-PB] t2 on t1.TruckID = t2.TruckID
inner join [TruckModel-PB] t3 on t1.TruckModelID = t3.ModelID
group by t3.Model, t3.Manufacturer, t1.Colour, t1.RegistrationNumber, t1.DailyRentalPrice
order by count(t2.TruckID) desc
My test:
create table A (
col1 varchar(255)
);
insert into A (col1) values ('A');
insert into A (col1) values ('A');
insert into A(col1) values ('A');
insert into A(col1) values ('A');
insert into A(col1) values ('A');
insert into A(col1) values ('A');
insert into A(col1) values ('A');
insert into A(col1) values ('B');
insert into A(col1) values ('B');
insert into A(col1) values ('B');
insert into A(col1) values ('B');
insert into A(col1) values ('B');
insert into A(col1) values ('B');
insert into A(col1) values ('C');
insert into A(col1) values ('C');
insert into A(col1) values ('C');
insert into A(col1) values ('C');
insert into A(col1) values ('C');
insert into A(col1) values ('D');
insert into A(col1) values ('D');
insert into A(col1) values ('D');
insert into A(col1) values ('D');
insert into A(col1) values ('D');
insert into A(col1) values ('E');
insert into A(col1) values ('E');
insert into A(col1) values ('E');
Select for MS SQL Server 2017:
select top(2) col1 from A group by col1 order by count(col1) desc;
Output:
col1
A
B

SQL Server Grouped results containing number and null values

I want to build a query which will return only the phase_ids that contain level_id values of BOTH numeric AND null
In the following example I would expect to return phase_id 1,3
DECLARE #tbl TABLE
(phase_id numeric(10,0) null,
type_id numeric(10,0) null,
level_id numeric(10,0) null)
INSERT #tbl VALUES (1,1,1)
INSERT #tbl VALUES (1,2,1)
INSERT #tbl VALUES (1,5,2)
INSERT #tbl VALUES (1,1,5)
INSERT #tbl VALUES (1,1,NULL)
INSERT #tbl VALUES (2,1,2)
INSERT #tbl VALUES (2,3,6)
INSERT #tbl VALUES (2,1,1)
INSERT #tbl VALUES (3,1,6)
INSERT #tbl VALUES (3,1,NULL)
SELECT * FROM #tbl
Thank you
count(*) counts all rows, count(level_id) counts non-null rows:
select phase_id
from tbl
group by phase_id
having count(*) <> count(level_id)
and count(level_id) > 0

How do I remove all but some records based on a threshold?

I have a table like this:
CREATE TABLE #TEMP(id int, name varchar(100))
INSERT INTO #TEMP VALUES(1, 'John')
INSERT INTO #TEMP VALUES(1, 'Adam')
INSERT INTO #TEMP VALUES(1, 'Robert')
INSERT INTO #TEMP VALUES(1, 'Copper')
INSERT INTO #TEMP VALUES(1, 'Jumbo')
INSERT INTO #TEMP VALUES(2, 'Jill')
INSERT INTO #TEMP VALUES(2, 'Rocky')
INSERT INTO #TEMP VALUES(2, 'Jack')
INSERT INTO #TEMP VALUES(2, 'Lisa')
INSERT INTO #TEMP VALUES(3, 'Amy')
SELECT *
FROM #TEMP
DROP TABLE #TEMP
I am trying to remove all but some records for those that have more than 3 names with the same id. Therefore, I am trying to get something like this:
id name
1 Adam
1 Copper
1 John
2 Jill
2 Jack
2 Lisa
3 Amy
I am not understanding how to write this query. I have gotten to the extent of preserving one record but not a threshold of records:
;WITH FILTER AS
(
SELECT id
FROM #TEMP
GROUP BY id
HAVING COUNT(id) >=3
)
SELECT id, MAX(name)
FROM #TEMP
WHERE id IN (SELECT * FROM FILTER)
GROUP BY id
UNION
SELECT id, name
FROM #TEMP
WHERE id NOT IN (SELECT * FROM FILTER)
Gives me:
1 Robert
2 Rocky
3 Amy
Any suggestions? Oh by the way, I don't care what records are preserved while merging.
You can do it using CTE
CREATE TABLE #TEMP(id int, name varchar(100))
INSERT INTO #TEMP VALUES(1, 'John')
INSERT INTO #TEMP VALUES(1, 'Adam')
INSERT INTO #TEMP VALUES(1, 'Robert')
INSERT INTO #TEMP VALUES(1, 'Copper')
INSERT INTO #TEMP VALUES(1, 'Jumbo')
INSERT INTO #TEMP VALUES(2, 'Jill')
INSERT INTO #TEMP VALUES(2, 'Rocky')
INSERT INTO #TEMP VALUES(2, 'Jack')
INSERT INTO #TEMP VALUES(2, 'Lisa')
INSERT INTO #TEMP VALUES(3, 'Amy')
SELECT *
FROM #TEMP;
WITH CTE(N) AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY id ORDER BY id)
FROM #Temp
)
DELETE CTE WHERE N>3;
SELECT *
FROM #TEMP;
DROP TABLE #TEMP
I will change your select like this (not tested)
select name from #temp group by name having count(id) > 3
then you can implement your query in a delete statement using your select as a where clause
in inner query you can use row_number function over (partition by id)
and then in outer query you have to give condition like below
select id,name from (
SELECT id,name, row_number() over (partition by id order by 1) count_id FROM #test
group by id, name )
where count_id <=3
If i got your question right, you need to get rows when id occurrence 3 or more times
select t1.name,t1.id from tbl1 t1
inner join tbl1 t2 on t1.id = t2.id
group by t1.name, t1.id
having count(t1.id) > 2

A simple but challenging SQL Question, at least I couldn't find a way out except doing it externally (c#)

I have an SQL Table which consists of 1 column only
Column Name
A
A
A
B
B
B
B
C
D
D
E
I need an SQL Code that returns the cut points. For the table above, it will return this:
Column Name
3
7
8
10
11
3 is the end of A's and 7 is the end of B's and 8 is the end of C's and so on...
Let's see what can you come up with :=)
Assuming the data can be sorted on your Column, the plan is to generate a row number for each row and do a group by to retrieve your data points.
SQL Server 2000
DECLARE #YourTable TABLE (Col VARCHAR(1))
CREATE TABLE #TempTable (ID INTEGER IDENTITY(1, 1), Col VARCHAR(1))
SET IDENTITY_INSERT #TempTable OFF
INSERT INTO #YourTable (Col) VALUES ('A')
INSERT INTO #YourTable (Col) VALUES ('A')
INSERT INTO #YourTable (Col) VALUES ('A')
INSERT INTO #YourTable (Col) VALUES ('B')
INSERT INTO #YourTable (Col) VALUES ('B')
INSERT INTO #YourTable (Col) VALUES ('B')
INSERT INTO #YourTable (Col) VALUES ('B')
INSERT INTO #YourTable (Col) VALUES ('C')
INSERT INTO #YourTable (Col) VALUES ('D')
INSERT INTO #YourTable (Col) VALUES ('D')
INSERT INTO #YourTable (Col) VALUES ('E')
INSERT INTO #TempTable
SELECT *
FROM #YourTable
ORDER BY Col
SELECT MAX(ID)
FROM #TempTable
GROUP BY Col
DROP TABLE #TempTable
SQL Server 2005
DECLARE #Table TABLE (Col VARCHAR(1))
INSERT INTO #Table VALUES ('A')
INSERT INTO #Table VALUES ('A')
INSERT INTO #Table VALUES ('A')
INSERT INTO #Table VALUES ('B')
INSERT INTO #Table VALUES ('B')
INSERT INTO #Table VALUES ('B')
INSERT INTO #Table VALUES ('B')
INSERT INTO #Table VALUES ('C')
INSERT INTO #Table VALUES ('D')
INSERT INTO #Table VALUES ('D')
INSERT INTO #Table VALUES ('E')
SELECT MAX(RowNumber)
FROM (SELECT RowNumber = ROW_NUMBER() OVER (ORDER BY Col), Col
FROM #Table) t
GROUP BY Col
with endings(columnname, ending) as
(
select columnname, row_number() over (order by columnname) as 'ending'
from theTable
)
select max(ending)
from endings
group by columnname
Solution for Oracle:
Assuming the name of the column is COL1,
SELECT COL1,MAX(ROWNUM)
FROM TEST_CHARS
GROUP BY COL1
ORDER BY COL1;