How to query rows matching for a particular string? - sql

This is how table looks like and here Empid and idnumber were unique for each employee and also an employee can have multiple badges with different badge number.
Now,I want to filter employees whose badge start with 6542 and 3214, ie employees carrying both badge starting from 6542 and 3214
Thank u
UPdate 1
There are some records which is having only a single badge starting from 6542 or 3214 . but I want only employees who is carrying both badges .

Do a GROUP BY, use HAVING to ensure both badges:
select empid, name
from Table
where badge like '6542-%' or badge like '3214-%'
group by empid, name
having count(distinct badge) > 1
Or use INTERSECT:
select empid, name from Table where badge like '6542-%'
intersect
select empid, name from Table where badge like '3214-%'

Just use like on badge field
Select empid, name
from TableName
where badge like '6542%' or badge like '3214%'
group by empid, name
having count(*)>1

this will work:
select empid from table_name where regexp_like(Badge,'^(6542)(.*)$')
intersect
select empid from table_name where regexp_like(Badge,'^(3214)(.*)$');
sql server equivalent:
select empid from table_name where PATINDEX ('^(6542)(.*)$',Badge) !=0
intersect
select empid from table_name where PATINDEX ('^(6542)(.*)$',Badge) !=0

We can use COUNT DISTINCT with CASE in HAVING as below
DECLARE #test AS TABLE(EMPID INT, Badge VARCHAR(50), idNumber INT, EName VARCHAR(50))
INSERT INTO #test VALUES
(1148, '6542-74488', 66448, 'Adam Jhon'),
(1148, '642-8562', 66448, 'Adam Jhon'),
(1148, '3214-52874', 66448, 'Adam Jhon'),
(1149, '3214-45220', 209541, 'Tom Koyaski'),
(1150, '3214-23134', 63339, 'Shirin Abdulla'),
(1151, '3214-42355', 65498, 'Linda Jhon'),
(1151, '6542-2546', 65498, 'Linda Jhon'),
(1152, '3214-47632', 208673, 'Gayeth'),
(1153, '6542-73085', 83209, 'Maria Smith'),
(1153, '3214-58073', 65498, 'Maria Smith'),
(1154, '3214-26735', 208673, 'Ayan Jacob'),
(1155, '642-26739', 53959, 'Wo Li')
SELECT empid, Ename
FROM #test
WHERE badge LIKE '6542%' OR badge LIKE '3214%'
GROUP BY empid, Ename
HAVING COUNT (DISTINCT(CASE WHEN badge like '6542%' THEN 1
WHEN badge LIKE '3214%' THEN 2 END))>1
OUTPUT:
empid Ename
1148 Adam Jhon
1151 Linda Jhon
1153 Maria Smith

just simply do like this
Select a.empid, a.name
from TableName as a
inner join TableName as b on a.Empid = b.Empid and a.idnumber = b.idnumber and b.badge like '3214%'
where a.badge like '6542%'

Related

Merging Duplicate Rows with SQL

I have a table that contains usernames, these names are duplicated in various forms, for example, Mr. John is replicated as John Mr. I want to combine the two rows using their unique phone numbers in SQL.
I want a new table in this form after removing the duplicates
you can do it with ROW_NUMBER window function.
First, you need to group the data by your unique column (Phone_Number), then sort by name.
Preparing the table and example data:
DECLARE #vCustomers TABLE (
Name NVARCHAR(25),
Phone_Number NVARCHAR(9),
Address NVARCHAR(25)
)
INSERT INTO #vCustomers
VALUES
('Mr John', '234881675', 'Lagos'),
('Mr Felix', '234867467', 'Atlanta'),
('Mrs Ayo', '234786959', 'Doha'),
('John Mr', '234881675', 'Lagos'),
('Mr Jude', '235689760', 'Rabat'),
('Ayo', '234786959', 'Doha'),
('Jude', '235689760', 'Rabat')
After that, removing the duplicate rows:
DELETE
vc
FROM (
SELECT
ROW_NUMBER() OVER(PARTITION BY Phone_Number ORDER BY Name DESC) AS RN
FROM #vCustomers
) AS vc
WHERE RN > 1
SELECT * FROM #vCustomers
As final, the result:
Name
Phone_Number
Address
Mr John
234881675
Lagos
Mr Felix
234867467
Atlanta
Mrs Ayo
234786959
Doha
Mr Jude
235689760
Rabat

Retrieving values from table 2 using table 1

I have two tables dept and work; values are like this
INSERT INTO DEPT(DEPTID, DEPTNAME) VALUES
( 1, 'DEPT1'),
(2, 'DEPT2'),
(3,'DEPT2'),
(4,'DEPT4'),
(5,'DEPT4'),
(6,'DEPT6');
INSERT INTO WORK (WORKID, DEPTID, SAL,CITYID) VALUES
( 100,1,1000,10),
( 100,2,2000,10),
( 200,1,2500,20),
( 300,3,1000,10),
( 300,6,3000,10),
( 300,6,1000,30)
;
For the given cityid ( work table), take all deptids for each deptname (from dept table ) and match in work table, if exists display count (count of deptids present in work table) and avgsal else 0 for count and avgsal all dept names in the same order present in dept table. Output should be like this
Cityid deptname count avg-sal
10 dept1 1 1000
10 dept2 2 1500
10 dept4 0 0
10 dept6 1 3000
Grandtotal 3 2333.33
I tried thru joins, but didnt work properly
You have a very strange department table -- containing duplicates.
In any case, this is a join and group by:
select 10 as cityid, coalesce(d.deptname, 'Total') as name,
count(w.workid) as cnt,
avg(sal) as average_salary
from dept d left join
work w
on w.deptid = d.deptid and w.cityid = 10
group by grouping sets ((w.cityid, d.deptname) ());
Here is a db<>fiddle.
Note that this returns the average salary as the average over the whole population. This is usually what one wants. The value is 1750, which looks correct to me.

Select same last names but not same names

I have a table with fname|lname|startyear|endyear
Take it that a person with same fname and lname is a unique person.
There can be multiple entries with the same fname|lname.
1)How do i find all the same last names belonging to different people?
Eg
'tom' |'jerry'|1990|1991|
'vlad' |'jerry'|1991|1992|
'tim' |'cook' |1991|1992|
'tim' |'cook' |1992|1993|
Output:
jerry
2)Which people (first and last names) served between 'Mary' 'Jane's two terms?
Eg
'mary' |'jane'|1989|1990|
'tom' |'jerry'|1990|1991|
'vlad' |'jerry'|1991|1992|
'tim' |'cook' |1991|1992|
'tim' |'cook' |1992|1993|
'mary' |'jane'|1993|1994
Output
tom jerry
vlad jerry
tim cook
1) In this below query, the inline view gets you all the unique combination of fname,lname's and its joined with the original table on lname that will give you all the unique lnames but have multilple first names.
SELECT lname
FROM table t1
INNER JOIN
( SELECT fname,lname
FROM table
GROUP BY fname,lname
HAVING COUNT(1) = 1
) t2
ON t1.lname = t2.lname;
2) In this query, the inline view will return the min year and max year of the terms served by Mary Jane and then its cross joined to the original table and the comparison is done on the startyear and endyear which will give you all the fname,lname's who served in between Mary Jane.
SELECT fname,lname
FROM table t1
CROSS JOIN
( SELECT MIN(startyear) AS minstart,MAX(endyear) AS maxend
FROM table
WHERE fname = 'Mary' AND lname = 'Jane'
) t2
WHERE t1.startyear >= t2.minstart AND t1.endyear <= t2.maxstart;

SQL Server : query to update record with latest entry

I have a table that maintains records of employers and employees' data. Something like this
EmployerName EmployerPhone EmployerAddress EmployeeName EmployeePhone EmployeeAddress Date
-------------------------------------------------------------------------------------------------------
John 12345 NewYork Harry 59786 NewYork 12-1-1991
Mac 22345 Bankok John 12345 Delhi 12-3-1991
Smith 54732 Arab Amar 59226 China 21-6-1991
Sarah 12345 Bhutan Mac 22345 NewYork 5-9-1991
Root 85674 NewYork Smith 54732 Japan 2-11-1991
I have another table that will have generic records on the basis of phone number (both employers and employees).
Table structure is as following
Phone Name Address
I want to put latest records according to date from Table1 to Table2 on the basis of phone..
Like this
Phone Name Address
-----------------------
59786 Harry NewYork
22345 Mac NewYork
59226 Amar China
12345 Sarah Bhutan
22345 Mac NewYork
85674 Root NewYork
54732 Smith Arab
I've written many queries but couldn't find anyone resulted as required.
Any kind of help will be appreciated.
For initialize the table without phone duplicates:
INSERT IGNORE INTO Table2 (Phone, Name, Address)
SELECT X.* FROM (
SELECT EmployeeName,EmployeePhone,EmployeeAddress FROM Table1
UNION
SELECT EmployerName,EmployerPhone,EmployerAddress FROM Table1
) X
WHERE NOT EXISTS (SELECT Phone FROM Table2 WHERE Phone=X.Phone)
I think this is what you are looking for if I understand your question correctly. Should work for a once-off
DECLARE #restbl TABLE
(
Name varchar(100),
Phone varchar(20),
Addr varchar(100),
[Date] date,
RecType varchar(100)
)
INSERT INTO #restbl
SELECT EmployerName, EmployerPhone, NULL, MAX([Date]), 'Employer'
FROM #tbl
GROUP BY EmployerName, EmployerPhone
INSERT INTO #restbl
SELECT EmployeeName, EmployeePhone, NULL, MAX([Date]), 'Employee'
FROM #tbl
GROUP BY EmployeeName, EmployeePhone;
WITH LatestData (Name, Phone, [Date])
AS
(
SELECT Name, Phone, MAX([Date])
FROM #restbl
GROUP BY Name, Phone
)
INSERT INTO FinalTable (Name, Phone, [Address])
SELECT DISTINCT ld.Name, ld.Phone, ISNULL(tEmployer.EmployerAddress, tEmployee.EmployeeAddress) AS [Address]
FROM LatestData ld
LEFT JOIN #tbl tEmployer ON ld.Name = tEmployer.EmployerName AND ld.Phone = tEmployer.EmployerPhone AND ld.Date = tEmployer.Date
LEFT JOIN #tbl tEmployee ON ld.Name = tEmployee.EmployeeName AND ld.Phone = tEmployee.EmployeePhone AND ld.Date = tEmployee.Date

ms-access 2010: count duplicate names per household address

I am currently working with a spreadsheet in MS Access 2010 which contains about 130k rows of information about people who voted in a local election recently. Each row has their residential information (street name, number, postcode etc.) and personal information (title, surname, forename, middle name, DOB etc.). Each row represents an individual person rather than a household (therefore in many cases the same residential address appears more than once as more than one person resides in a particular household).
What I want to achieve is basically to create a new field in this dataset called 'count'. I want this field to give me a count of how many different surnames reside at a single address.
Is there an SQL script that will allow me to do this in Access 2010?
+------------------+----------+-------+---------+----------+-------------+
| PROPERTYADDRESS1 | POSTCODE | TITLE | SURNAME | FORENAME | MIDDLE_NAME |
+------------------+----------+-------+---------+----------+-------------+
FAKEADDRESS1 EEE 5GG MR BLOGGS JOE N
FAKEADDRESS2 EEE 5BB MRS BLOGGS SUZANNE P
FAKEADDRESS3 EEE 5RG MS SMITH PAULINE S
FAKEADDRESS4 EEE 4BV DR JONES ANNE D
FAKEADDRESS5 EEE 3AS MR TAYLOR STUART A
The following syntax has got me close so far:
SELECT COUNT(electoral.SURNAME)
FROM electoral
GROUP BY electoral.UPRN
However, instead of returning me all 130k odd rows, it only returns me around 67k rows. Is there anything I can do to the syntax to achieve the same result, but just returning every single row?
Any help is greatly appreciated!
Thanks
You could use something like this:
select *,
count(surname) over (partition by householdName)
from myTable
If you have only one column which contains the name,
ex: Rob Adams
then you can do this to have all the surnames in a different column so it will be easier in the select:
SELECT LEFT('HELLO WORLD',CHARINDEX(' ','HELLO WORLD')-1)
in our example:
select right (surmane, charindex (' ',surname)-1) as surname
example on how to use charindex, left and right here:
http://social.technet.microsoft.com/wiki/contents/articles/17948.t-sql-right-left-substring-and-charindex-functions.aspx
if there are any questions, leave a comment.
EDIT: I edited the query, had a syntax error, please try it again. This works on sql server.
here is an example:
create table #temp (id int, PropertyAddress varchar(50), surname varchar(50), forname varchar(50))
insert into #temp values
(1, 'hiddenBase', 'Adamns' , 'Kara' ),
(2, 'hiddenBase', 'Adamns' , 'Anne' ),
(3, 'hiddenBase', 'Adamns' , 'John' ),
(4, 'QueensResidence', 'Queen' , 'Oliver' ),
(5, 'QueensResidence', 'Queen' , 'Moira' ),
(6, 'superSecretBase', 'Diggle' , 'John' ),
(7, 'NandaParbat', 'Merlin' , 'Malcom' )
select * from #temp
select *,
count (surname) over (partition by PropertyAddress) as CountMembers
from #temp
gives:
1 hiddenBase Adamns Kara 3
2 hiddenBase Adamns Anne 3
3 hiddenBase Adamns John 3
7 NandaParbat Merlin Malcom 1
4 QueensResidence Queen Oliver 2
5 QueensResidence Queen Moira 2
6 superSecretBase Diggle John 1
Your query should look like this:
select *,
count (SURNAME) over (partition by PropertyAddress) as CountFamilyMembers
from electoral
EDIT
If over partition by isn't supported, then I guess you can get to your desired result by using group by
select *,
count (SURNAME) over (partition by PropertyAddress) as CountFamilyMembers
from electoral
group by -- put here the fields in the select (one by one), however you can't write group by *
GROUP BY creates an aggregate query, so it's by design that you get fewer records (one per UPRN).
To get the count for each row in the original table, you can join the table with the aggregate query:
SELECT electoral.*, elCount.NumberOfPeople
FROM electoral
INNER JOIN
(
SELECT UPRN, COUNT(*) AS NumberOfPeople
FROM electoral
GROUP BY UPRN
) AS elCount
ON electoral.UPRN = elCount.UPRN
Given the update I want to post another answer. Try it like this:
create table #temp2 ( PropertyAddress1 varchar(50), POSTCODE varchar(20), TITLE varchar (20),
surname varchar(50), FORENAME varchar(50), MIDDLE_NAME varchar (50) )
insert into #temp2 values
('FAKEADDRESS1', 'EEE 5GG', 'MR', 'BLOGGS', 'JOE', 'N'),
('FAKEADDRESS1', 'EEE 5BB', 'MRS', 'BLOGGS', 'SUZANNE', 'P'),
('FAKEADDRESS2', 'EEE 5RG', 'MS', 'SMITH', 'PAULINE', 'S'),
('FAKEADDRESS3', 'EEE 4BV', 'DR', 'JONES', 'ANNE', 'D'),
('FAKEADDRESS4', 'EEE 3AS', 'MR', 'TAYLOR', 'STUART', 'A')
select PropertyAddress1, surname,count (#temp2.surname) as CountADD
into #countTemp
from #temp2
group by PropertyAddress1, surname
select * from #temp2 t2
left join #countTemp ct
on t2.PropertyAddress1 = ct.PropertyAddress1 and t2.surname = ct.surname
This yields:
PropertyAddress1 POSTCODE TITLE surname FORENAME MIDDLE_NAME PropertyAddress1 surname CountADD
FAKEADDRESS1 EEE 5GG MR BLOGGS JOE N FAKEADDRESS1 BLOGGS 2
FAKEADDRESS1 EEE 5BB MRS BLOGGS SUZANNE P FAKEADDRESS1 BLOGGS 2
FAKEADDRESS2 EEE 5RG MS SMITH PAULINE S FAKEADDRESS2 SMITH 1
FAKEADDRESS3 EEE 4BV DR JONES ANNE D FAKEADDRESS3 JONES 1
FAKEADDRESS4 EEE 3AS MR TAYLOR STUART A FAKEADDRESS4 TAYLOR 1