This question already has answers here:
Is there a way to access the "previous row" value in a SELECT statement?
(9 answers)
Closed 4 months ago.
Lets say I have a table like this;
Id
Name
1
John
2
Doe
5
Rose
11
Michael
15
Pedro
and my select query like this;
Id
Name
1
John
5
Rose
I want to select next rows according to my query which like this;
Id
Name
2
Doe
11
Michael
1 Johns next row is 2 Doe and 5 Roes's next row 11 Michael
One of many ways to do this:
WITH
RowNumbers AS (
SELECT
*,
ROW_NUMBER() OVER (ORDER BY ID) AS RowNumber
FROM
TableName -- replace with your table name
)
SELECT
Id,
Name
FROM
RowNumbers
WHERE
RowNumber IN (
SELECT
RowNumber+1
FROM
RowNumbers
WHERE
Name IN ('John', 'Rose')
)
;
You could use a CTE to create row_numbers and then select and join to it.
create table my_data (
id integer,
name varchar(20)
);
insert into my_data (id, name) values
(1, 'john'),
(2, 'doe'),
(5, 'rose'),
(11, 'michael'),
(15, 'pedro');
with row_data as (
select id, name,
row_number() over (order by id) as rn
from my_data
)
select b.id, b.name
from row_data a
join row_data b
on a.rn + 1 = b.rn
where a.name in ('john','rose')
id
name
2
doe
11
michael
fiddle
Related
I have data in the below format
id idnew
1 2
3 4
2
4 7
6 8
7
Result Should be something like this
ID should be followed by idnew
1
2
3
4
2
4
7
6
8
7
Thanks in advance
This should maintain the order:
SELECT id
FROM (
SELECT id, ROW_NUMBER() OVER (ORDER BY id) AS RowNumber
FROM myTable
UNION ALL
SELECT idnew, ROW_NUMBER() OVER (ORDER BY idnew) +
(SELECT COUNT(*) FROM dbo.myTable) AS RowNumber
FROM myTable
WHERE idnew IS NOT NULL
) a
ORDER BY RowNumber
I am assuming the id column is NOT NULL-able.
NOTE: If you want to keep the NULL values from the idnew column AND maintain the order, then remove the WHERE clause and ORDER BY id in the second select:
SELECT id
FROM (
SELECT id, ROW_NUMBER() OVER (ORDER BY id) AS RowNumber
FROM myTable
UNION ALL
SELECT idnew, ROW_NUMBER() OVER (ORDER BY id) +
(SELECT COUNT(*) FROM dbo.myTable) AS RowNumber
FROM myTable
) a
ORDER BY RowNumber
This is fully tested, try it here: https://rextester.com/DVZXO21058
Setting up the table as you described:
CREATE TABLE myTable (id INT, idnew INT);
INSERT INTO myTable (id, idnew)
VALUES (1, 2),
(3, 4),
(2, NULL),
(4, 7),
(6, 8),
(7, NULL);
SELECT * FROM myTable;
Here is the query to do the trick:
SELECT mixed_id FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS row_num,
id,
idnew
FROM myTable
) AS x
UNPIVOT
(
mixed_id for item in (id, idnew)
) AS y
WHERE mixed_id IS NOT NULL
ORDER BY row_num, mixed_id;
In order not to further complicate the query, this is taking advantage of 'id' would rank ahead of 'idnew' as a string. I believe string ranking is not the key issue here.
Using Cross Apply
;WITH CTE (id,idnew)
AS
(
SELECT 1,2 UNION ALL
SELECT 3,4 UNION ALL
SELECT 2,NULL UNION ALL
SELECT 4,7 UNION ALL
SELECT 6,8 UNION ALL
SELECT 7,NULL
)
SELECT New
FROM CTE
CROSS APPLY ( VALUES (id),(idnew))AS Dt (New)
WHERE dt.New IS NOT NULL
Result
New
---
1
2
3
4
2
4
7
6
8
7
I have a table with a following data:
ID | Name
---------
1 | John
2 | Alice
And when I want to select 5 rows I want to get the next data:
ID | Name
---------
1 | John
2 | Alice
1 | John
2 | Alice
1 | John
Is there any ideas how to make this?
-- to create a sample table.
CREATE TABLE table1 (ID BIGINT, NAME VARCHAR(255))
INSERT INTO table1 VALUES (1, 'John'), (2, 'Alice')
-- set number of rows you need
DECLARE #RowsReqd INT = 5
-- find out the max ID we want to generate
DECLARE #Limit INT
SELECT #Limit = MAX(ID) FROM table1
-- generate the list
;WITH NumbersList
AS (
SELECT 1 AS Number, 1 AS ID
UNION ALL
SELECT Number + 1, Number % #Limit + 1 FROM NumbersList
WHERE Number < #RowsReqd
)
SELECT T.*
FROM NumbersList NL
INNER JOIN table1 T ON T.ID = NL.ID
ORDER BY NL.Number
OPTION (MAXRECURSION 10000) -- increase this value to generate more numbers
OUTPUT:
ID NAME
1 John
2 Alice
1 John
2 Alice
1 John
Works for n > 1 rows:
;WITH cte AS (
SELECT *
FROM (VALUES
(1, 'John'),
(2, 'Alice')
) AS t(ID, Name)
)
,res AS (
SELECT id,
name,
ROW_NUMBER() OVER (partition by id ORDER BY ID) as pid
FROM cte
UNION ALL
SELECT c.id,
c.name,
pid + 1
FROM res r
INNER JOIN cte c
ON pid = c.id
)
SELECT TOP 5
id,
name
FROM res
Output:
id name
----------- -----
1 John
2 Alice
1 John
2 Alice
1 John
(5 row(s) affected)
I have one table in SQL in this form:
id Name Date
----------------------------
1 john 04/05/2014
2 andi 12/05/2014
3 mark 05/08/2014
4 sofie 05/11/2014
5 john 12/12/2014
5 mark 15/12/2014
and i want to select data in this form "distinct"
id Name Date
---------------------------
1 john 12/12/2014
2 mark 15/12/2014
3 andi 12/05/2014
try something like:
SELECT t1.*
FROM <table_name> t1
WHERE t1.date = (SELECT MAX(t2.date)
FROM <table_name> t2
WHERE t2.name = t1.name)
Try this:
-- sample data
create table #tbl (id int, name nvarchar(20), [date] date);
insert into #tbl (id, name, [date]) values
(1, 'john', '2014-05-04'),
(2, 'andi', '2014-05-12'),
(3, 'mark', '2014-08-05'),
(4, 'sofie', '2014-11-05'),
(5, 'john', '2014-12-12'),
(5, 'mark', '2014-12-15');
-- solution
with ranked as
(
select id, name, [date]
, row_number() over(partition by name order by datediff(day, [date], getdate())) [rank]
from #tbl
)
select id, name, [date] from ranked where [rank] = 1;
-- cleanup
drop table #tbl;
Result
ID NAME DATE
----------------------
2 andi 2014-05-12
5 john 2014-12-12
5 mark 2014-12-15
4 sofie 2014-11-05
This solution ranks original dataset by name and in case when there are the same names ranks them by count of days between today and [date]. So the result dataset consists of rows with the unique names and the rows with names which [date] is closest to today.
Check SQLFiddle
Looks like you may want
SELECT name, MAX(date)
FROM table
GROUP BY name
However, from your example it's impossible to infer on what criterion you'd exclude sofie (and what does a duplicate id mean in your example table -- id is normally used to denote a unique identifier).
I have an interesting problem here. But it is just for knowledge because I already solve it in a non elegant way.
I have a table that have costumers and they can be holders or dependants and this relation is described as a
family. Each family can have only a holder and 0-n dependants. A holder is identified by an H and a Dependant by a D.
What I need is a way to order the data by name of holder and theirs dependants. So the sample data below
idcostumer name idfamily relation
1 Natalie Portman 1 H
2 Mark Twain 3 D
3 Carl Sagan 2 D
4 Bob Burnquist 2 H
5 Sheldon Cooper 1 D
6 Anakin Skywalker 4 H
7 Luke Skywalker 4 D
8 Leia Skywalker 4 D
9 Burnquist Jr. 2 D
10 Micheal Jackson 3 H
11 Sharon Stone 1 H
12 Michelle Pfeiffer 3 D
Is it possible to get the above results in just one query? As you can see the order is name (just for the holders)
idcostumer name idfamily relation
6 Anakin Skywalker 4 H
8 Leia Skywalker 4 D
7 Luke Skywalker 4 D
4 Bob Burnquist 2 H
9 Burnquist Jr. 2 D
3 Carl Sagan 2 D
10 Micheal Jackson 3 H
2 Mark Twain 3 D
12 Michelle Pfeiffer 3 D
11 Sharon Stone 1 H
1 Natalie Portman 1 D
5 Sheldon Cooper 1 D
The test case data for this example.
create table costumer (
idcostumer integer primary key,
name varchar2(20),
idfamily integer,
relation varchar2(1)
);
This is the inserts statments for this table:
insert into costumer values ( 1 , 'Natalie Portman' , 1, 'D');
insert into costumer values ( 2 , 'Mark Twain' , 3, 'D');
insert into costumer values ( 3 , 'Carl Sagan' , 2, 'D');
insert into costumer values ( 4 , 'Bob Burnquist' , 2, 'H');
insert into costumer values ( 5 , 'Sheldon Cooper' , 1, 'D');
insert into costumer values ( 6 , 'Anakin Skywalker' , 4, 'H');
insert into costumer values ( 7 , 'Luke Skywalker' , 4, 'D');
insert into costumer values ( 8 , 'Leia Skywalker' , 4, 'D');
insert into costumer values ( 9 , 'Burnquist Jr.' , 2, 'D');
insert into costumer values ( 10, 'Micheal Jackson' , 3, 'H');
insert into costumer values ( 11, 'Sharon Stone' , 1, 'H');
insert into costumer values ( 12, 'Michelle Pfeiffer', 3, 'D');
I've tried some things, create a father sun relationship with connect by statement and familyid concatenated with the relation.
Used a row_count with a over clause ordering by relation desc and family id, but this way I lost the name order.
If I understand you correctly, you want to first order the families by the name of the holder, then by the names of the dependents. The following does that.
with family_order as (
select idfamily, rownum r from (
select idfamily from costumer where relation = 'H' order by name
)
)
select c.* from costumer c
inner join family_order fo on c.idfamily = fo.idfamily
order by fo.r, relation desc, name
Fiddle here
Try:
select * from table order by idfamily desc, relation desc, name asc
Link to Fiddle
For un-natural order you can use "union all":
select * from (select idcostumer, name, idfamily, relation from costumer
where idfamily > 3
order by idfamily desc, relation desc, name asc)
union all
select * from (
select idcostumer, name, idfamily, relation from costumer
where idfamily = 2
order by idfamily desc, relation desc, name asc)
union all
select * from (
select idcostumer, name, idfamily, relation from costumer
where idfamily != 2 and idfamily < 4
order by idfamily desc, relation desc, name asc)
Link to Fiddle
I have a table with data
ID Name
1 John
2 Robert
3 John
4 Sam
5 Jack
6 Sam
Now i want ony the the duplicate names ony through query
ie..,
Name
John
Sam
SELECT Name
FROM YourTable
GROUP BY Name
HAVING COUNT(*) > 1
CREATE TABLE MyTable (
ID int
, Name nvarchar(50)
)
INSERT MyTable VALUES ( 1, 'John' )
INSERT MyTable VALUES ( 2, 'Robert' )
INSERT MyTable VALUES ( 3, 'John' )
INSERT MyTable VALUES ( 4, 'Sam' )
INSERT MyTable VALUES ( 5, 'Jack' )
INSERT MyTable VALUES ( 6, 'Sam' )
SELECT
Name
FROM
MyTable
GROUP BY
Name
HAVING
COUNT(*) > 1
DROP TABLE MyTable
Results:
Name
--------------------------------------------------
John
Sam
with temp as (
select Name, count(Name) as countOfNames
from myTable
group by Name
)
select Name from temp
where countOfNames > 1
select columnname,count(column name) from tablename group by column name having count(*)>1