Insert blank row in every row - sql

I have a result like this:
name
Sally
Dan
Andy
Jackson
I used this query:
SELECT name from NAMEINFO where nNameIndex<5
and I want to get result like this:
name
Sally
(blank)
Dan
(blank)
Andy
(blank)
Jackson
(blank)
I tried query like this:
select name
from (
select top 100 percent *
from (
SELECT nNameIndex, name
FROM NAMEINFO
union all
select nNameIndex, ''
from NAMEINFO
) as t
order by 1
) as r
but result is:
name
Sally
Dan
Andy
Jackson
(blank)
(blank)
(blank)
(blank)
I want to insert blank row into every row in my SQL result.
Where should I change my code to get wanted result?

select name, ROW_NUMBER() over (order by name) pos from NAMEINFO where nNameIndex < 5
union all
select '', ROW_NUMBER() over (order by name) from NAMEINFO where nNameIndex < 5
order by pos, name desc
but really you should not do this in your database but in the consuming application.

In your initial query, you almost have it:
select name
from (
SELECT nNameIndex, name
FROM NAMEINFO
union all
select nNameIndex, ''
from NAMEINFO
) as t
order by nNameIndex

You can try ROW_NUMBER() to achieve the results.
DECLARE #table table(name varchar(50))
insert into #table
values
('Sally')
,('Dan')
,('Andy')
,('Jackson');
SELECT name
from
(
select name, ROW_NUMBER() OVER (ORDER BY name) as rnk from #table
union all
SELECT '',ROW_NUMBER() OVER (ORDER BY (SELECT null)) as rnk from #table
) as t
order by rnk,name desc
+---------+
| name |
+---------+
| Andy |
| |
| Dan |
| |
| Jackson |
| |
| Sally |
| |
+---------+

Related

Get custom Distinct Values from column table

Table data and expected data as below
I wanted to select the distinct ID and Name, irrespective of branch. But I want the branch name to be displayed.
If branch need not be displayed I can use substring. Can the result be achieved using CTE.
As you don't appear to care about which 'branch' needs to be returned, you can simply use a row_number within a CTE to return just one result per ID value:
declare #t table(ID int,Name varchar(20));
insert into #t values
(10,'Manoj (CS)')
,(10,'Manoj (IS)')
,(20,'Ajay (CS)')
,(20,'AJAY (IS)')
,(30,'Sunjay(EC)')
,(40,'Lina(IS)')
,(40,'Lina(CS)')
,(40,'Lina(EC)')
,(50,'Mary(IS)')
,(50,'Mary(EC)');
with d as
(
select ID
,Name
,row_number() over (partition by ID order by Name) as rn
from #t
)
select ID
,Name
from d
where rn = 1;
Output:
+----+------------+
| ID | Name |
+----+------------+
| 10 | Manoj (CS) |
| 20 | Ajay (CS) |
| 30 | Sunjay(EC) |
| 40 | Lina(CS) |
| 50 | Mary(EC) |
+----+------------+
If you do have a preference for the (CS) branch however, you would need to alter the row_number slightly:
with d as
(
select ID
,Name
,row_number() over (partition by ID
order by case when right(Name,4) = '(CS)'
then 1
else 2
end
,Name
) as rn
from #t
)
select ID
,Name
from d
where rn = 1;
You can use row_number() function with TIES :
select top (1) with ties *
from table t
order by row_number() over (partition by id order by name);
As mentioned in the comments: Change your datamodel.
If you must live with the table as is, all you want is: all student IDs, each with one branhc/subject name arbitrarily picked. This can be achieved with a simple aggregation:
select id, min(name) from mytable group by id;

SQL get a list of duplicate groups with a number of occurrences

I am stuck on what should be a simple query but I can't seem to get the result I desire.
I have a list of people with the following attributes ID, GroupNo, LastName.
Multiple people may be assigned to the same GroupNo and they can have different or the same Last Names. I am only interested in a list of people that have more than one Last Name assigned to the same GroupNo. I also need to know how many occurrences are in each GroupNo / LastName combination.
For example,
ID| GroupNo | LastName
1 | 003000 | MURAD
2 | 003000 | MURAD
3 | 003000 | MURAD
4 | 004020 | MAZZA
5 | 004020 | BOOTH
6 | 010930 | ZHANG
7 | 010930 | YAN
8 | 010930 | ZHANG
result should be:
GroupNo | LastName | Occurences
004020 | MAZZA | 1
004020 | BOOTH | 1
010930 | ZHANG | 2
010930 | YAN | 1
I tried to play with OVER(Partition By...) clause but not with much luck.
Any assistance is highly appreciated!
Thank you.
I found your result with this way
DECLARE #test AS TABLE(ID INT ,GroupNo VARCHAR(10),LastName VARCHAR(100))
INSERT INTO #test
(
ID,
GroupNo,
LastName
)
VALUES(1,'003000','MURAD'),(2,'003000','MURAD'),(3,'003000','MURAD'),(1,'004020','MAZZA'),(1,'004020','BOOTH')
,(1,'010930','ZHANG'),(1,'010930','YAN'),(1,'010930','ZHANG')
SELECT t2.GroupNo,t2.LastName,COUNT(*)AS cnt FROM(
SELECT res.GroupNo , COUNT(*) AS cnt1 FROM(
SELECT t.GroupNo,t.LastName,COUNT(*) AS cnt FROM #test AS t
GROUP BY t.GroupNo , t.LastName) res
GROUP BY res.GroupNo
HAVING COUNT(*) > 1) res2
INNER JOIN #test AS t2 ON t2.GroupNo = res2.GroupNo
GROUP BY t2.GroupNo,t2.LastName
You can do it just using group by and having to get only the ones that have more than one row:
SELECT GroupNo,LastName,COUNT(*) AS Occurences
FROM your_table
GROUP BY GroupNo,LastName
HAVING COUNT(*)>1
Here is a method using window functions:
select groupno, lastname, cnt
from (select groupno, lastname, count(*) as cnt,
min(lastname) over (partition by groupno) as min_lastname,
max(lastname) over (partition by groupno) as max_lastname
from t
group by groupno, lastname
) gl
where min_lastname <> max_lastname
order by groupno, lastname;
Here is another way to phrase it, without window functions:
select groupno, lastname, count(*) as cnt
from t
where exists (select 1
from t t2
where t2.groupno = t.groupno and t2.lastname <> t.lastname
)
group by groupno, lastname
order by groupno, lastname;

SQL Server : select from duplicate columns where date newest

I have inherited a SQL Server table in the (abbreviated) form of (includes sample data set):
| SID | name | Invite_Date |
|-----|-------|-------------|
| 101 | foo | 2013-01-06 |
| 102 | bar | 2013-04-04 |
| 101 | fubar | 2013-03-06 |
I need to select all SID's and the Invite_date, but if there is a duplicate SID, then just get the latest entry (by date).
So the results from the above would look like:
101 | fubar | 2013-03-06
102 | bar | 2013-04-04
Any ideas please.
N.B the Invite_date column has been declared as a nvarchar, so to get it in a date format I am using CONVERT(DATE, Invite_date)
You can use a ranking function like ROW_NUMBER or DENSE_RANK in a CTE:
WITH CTE AS
(
SELECT SID, name, Invite_Date,
rn = Row_Number() OVER (PARTITION By SID
Order By Invite_Date DESC)
FROM dbo.TableName
)
SELECT SID, name, Invite_Date
FROM CTE
WHERE RN = 1
Demo
Use Row_Number if you want exactly one row per group and Dense_Rank if you want all last Invite_Date rows for each group in case of repeating max-Invite_Dates.
select t1.*
from your_table t1
inner join
(
select sid, max(CONVERT(DATE, Invite_date)) mdate
from your_table
group by sid
) t2 on t1.sid = t2.sid and CONVERT(DATE, t1.Invite_date) = t2.mdate
select
SID,name,MAX(Invite_date)
FROM
Table1
GROUP BY
SID
http://sqlfiddle.com/#!2/6b6f66/1

Data Matching with SQL and assigning Identity ID's

How to write a query that will match data and produce and identity for it.
For Example:
RecordID | Name
1 | John
2 | John
3 | Smith
4 | Smith
5 | Smith
6 | Carl
I want a query which will assign an identity after matching exactly on Name.
Expected Output:
RecordID | Name | ID
1 | John | 1X
2 | John | 1X
3 | Smith | 1Y
4 | Smith | 1Y
5 | Smith | 1Y
6 | Carl | 1Z
Note: The ID should be unique for every match. Also, it can be numbers or varchar.
Can somebody help me with this? The main thing is to assign the ID's.
Thanks.
How about this:
with temp as
(
select 1 as id,'John' as name
union
select 2,'John'
union
select 3,'Smith'
union
select 4,'Smith'
union
select 5,'Smith'
union
select 6,'Carl'
)
SELECT *, DENSE_RANK() OVER
(ORDER BY Name) as NewId
FROM TEMP
Order by id
The first part is for testing purposes only.
Please try:
SELECT *,
Rank() over (order by Name ASC)
FROM table
This structure seems to work:
CREATE TABLE #Table
(
Department VARCHAR(100),
Name VARCHAR(100)
);
INSERT INTO #Table VALUES
('Sales','michaeljackson'),
('Sales','michaeljackson'),
('Sales','jim'),
('Sales','jim'),
('Sales','jill'),
('Sales','jill'),
('Sales','jill'),
('Sales','j');
WITH Cte_Rank AS
(
SELECT [Name],
rw = ROW_NUMBER() OVER (ORDER BY [Name])
FROM #Table
GROUP BY [Name]
)
SELECT a.Department,
a.Name,
b.rw
FROM #Table a
INNER JOIN Cte_Rank b
ON a.Name = b.Name;

Get first or most repeated value from a group by in SQL Server

I have an ugly table with codes and names from a source I can't control, which is like this one (OriginalTable):
Code | Name
--------------------
001-001 | Name1_a
001-002 | Name1_a
001-002 | Name1_b
001-003 | Name1_a
002-001 | Name2_a
002-001 | Name2_b
002-002 | Name2_a
003-001 | Name3
...
The problem is that I need an unique name for the first 3 digits of each code (SmallCode), like in the following table:
Id | Code | Name
--------------------
1 | 001 | NameX
2 | 002 | NameY
3 | 003 | NameZ
The criteria I want use for choosing a name is that it should be the most repeated name or the first one in each SmallCode.
For example NameX is the most repeated name on of all codes starting with 001 or the first one (Name1_a in both cases). Same with NameY for 002 and NameZ for 003.
Right now I was using this query:
select Substring(Code,1,3) as SmallCode, Code, Name
into #tmpCode
from OriginalTable
select SmallCode, Min(Code) as Code
into #tmpReducedCode
from #tmpCode
group by SmallCode
insert into ResultTable (Code, Name)
select a.SmallCode, a.Name
from #tmpCode a
inner join #tmpReducedCode b
on a.Code = b.Code
But this is my result, which is wrong because there are 2 different names for code 002-001 (Name2_a, Name2_b)
1 | 001 | Name1_a
2 | 002 | Name2_a
3 | 002 | Name2_b
4 | 003 | Name3
So the question is: How can I separate OriginalTable into those 2 tables choosing the most repeated or first appearing name for each small code?
For the first table:
select Substring(Code,1,3) as SmallCode, Code, Name
into #tmpCode
from OriginalTable
select SmallCode, Name
into #tmpReducedCode
from (
select SmallCode, Name, row_number() over (partition by SmallCode order by Total desc) rn
from (
select SmallCode, Name, count(*) Total
from #tmpCode
group by SmallCode, Name) x) y
where rn=1;
select distinct a.SmallCode, b.Name
from #tmpCode a
inner join #tmpReducedCode b
on left(a.Code,3) = b.SmallCode
I think the best way to do this is with window functions:
select cast(LEFT(code, 3) as int) as id,
RIGHT(code, 3) as code,
name
from (select cn.*, ROW_NUMBER() over (partition by code order by cnt desc) as seqnum
from (select code, name, COUNT(*) as cnt
from OriginalTable ot
group by code, name
) cn
) cn
where seqnum = 1
This assumes you are using SQL Server 2005 or a more recent version.
Run subquery for each code:
select distinct substring(Code,1,3) as "Code",
(select top 1 Name
from OrginalTable tab2
where substring(tab2.Code,1,3)=substring(tab1.Code,1,3)
group by substring(Code,1,3), Name
order by count(Name) desc) as "Name"
from OrginalTable tab1;