SQL: How to return records with more than 1 row of data - sql

I'm stuck on a problem where I am creating a report and need to show records which have two or more bank accounts (some of our employees are international and get paid in more than one currency).
The report I created brings back all employees and their bank account information. However, I want this report only to bring back employees with 2 or more bank accounts.
Here is some test data below:
As you can see, Gareth has more than one bank account - what filter can I write to just bring back his record?

Assuming it is mysql, sqlite and even postgresql (I think). it should be
SELECT * FROM table_name WHERE "First Name" = "Gareth";
However if you are using the MySQL binding for excel be sure that "Gareth" is listed for each account he owns. It may look cleaner but SQL will interpret the row beneath "Gareth" as "". Doing this will also mean you will need a new index, "First Name" can't be set as "UNIQUE". Also having spaces in columns is pretty ugly SQL syntax best to use camelCase or under_scores.

Assuming Person_Number as the primary key of the table accounts
SELECT * FROM accounts WHERE accounts.First_Name in
(SELECT a.First_Name
FROM accounts a
INNER JOIN accounts b
ON a.Person_Number = b.Person_Number
WHERE a.First_Name = b.First_Name
AND a.Bank_Account_Name <> b.Bank_Account_Name
);

Try this if you are using database like oracle, sqlserver....
select b1.* from account_info_table b1 where exists (select 1 from account_info_table b2 where b1.first_name=b2.first_name group by b2.first_name having count(*)>2);
or
select * from account_info_table where first_name in (select first_name from account_info_table group by first_name having count(*)>2);

Use This Code :
;WITH _CTE AS
(
SELECT *,ROW_NUMBER()OVER(PARTITION BY FirstName Order By FirstName)ROWNO FROM #Temp
)SELECT FirstName,BankAccountName,BankBranchName,BankAccountNo,SortCode FROM _CTE WHERE ROWNO > 1

select empleado from empleados
group by empleado
having count(*) > 1

Related

How to search for matching staff number in sql

I am new to sql and trying to come up with a sql query which will list me the duplicate staff which were created in our system.
We have one staff which is created with id as 1234 and the same user has another account starting with staff id 01234. Is there anyway i can get the matching staff
Once i come up with correct duplicates i will than want to delete the accounts which don't have "0" at the start e.g deleted 1234 and only keep 01234
below is the sql
SELECT tps_user.tps_title AS [Name] , tps_user_type.tps_title AS [User Type]
FROM tps_user INNER JOIN
tps_user_type ON tps_user.tps_user_type_guid = tps_user_type.tps_guid
WHERE (tps_user.tps_title IN
(SELECT tps_title AS users
FROM tps_user AS t1
WHERE (tps_deleted = 0)
GROUP BY tps_title
HAVING (COUNT(tps_title) > 1))) AND (tps_user.tps_deleted = 0)
When you do you select try this:
SELECT DISTINCT CONVERT(INT,ID)
FROM your_table
WHERE ...
OR
SELECT ID
FROM your_table
WHERE ...
GROUP BY ID
This will convert all the id's to an int temporarily so when the distinct evaluates duplicates everything will be uniform to give you an accurate representation of the duplicates.
IF you don't want to convert them maybe convert them and insert them into a temporary table and add a flag to which ones have a leading zero. Or convert them then append a zero after you delete the duplicates since you want that anyway. It is easy to append a 0.
the below query will give you the list of duplicates with same Name and title. -
SELECT tps_user.tps_title AS [Name] ,
tps_user_type.tps_title AS [UserType],
COUNT(*) Duplicate_Count
FROM tps_user
INNER JOIN tps_user_type
ON tps_user.tps_user_type_guid = tps_user_type.tps_guid
group by tps_user.tps_title, tps_user_type.tps_title
having COUNT(*) > 1
order by Duplicate_Count desc
Select t1.stringId
from mytable t1
inner join mytable t2 on Convert(INT, t1.intId) = CONVERT(INT, t2.intId)
where t1.stringId not like '0%'
This should list all the persons that have duplicates but do not start with 0.

SQL: Removing ALL rows that have repeated values

I've got a table with columns:
Acct_no, PSTL_CODE, NAME, phone
I'm trying to get rid of all rows that share the same PSTL_CODE and phone (i.e. dump the ones where there's his & hers accounts, and similar scenarios)
I've pulled together the following which I think should only return rows with a unique PSTL_CODE:
SELECT * FROM Sheet1
WHERE PSTL_CODE IN
(SELECT PSTL_CODE FROM SHEET1
GROUP BY PSTL_CODE HAVING COUNT(PSTL_CODE) =1)
ORDER BY phone
and it's close-ish, but it's still returning one row where there are two accounts at the same PSTL_CODE.
and I'm stuck with Access 2007, so I can't do:
SELECT * FROM Sheet1
EXCEPT
(SELECT PSTL_CODE FROM SHEET1
GROUP BY PSTL CODE HAVING COUNT(*) >1)
ORDER BY phone
in order to just scythe away the multiples.
Help!
Try using Exists
Considering that your unique combination is PSTL_CODE and phone
SELECT *
FROM sheet1 a
WHERE EXISTS (SELECT 1
FROM sheet1 b
WHERE a.pstl_code = b.pstl_code
AND a.phone = b.phone
HAVING Count(*) = 1)
ORDER BY phone
It is better to define a Unique Constraint on PSTL_CODE and phone columns which helps you to avoid duplicate records in table
If I understand the business logic correctly you are attempting to eliminate couples living together from the query. you are grouping by phone also which seems to be causing the error. Is there a logical business reason for two people to live in the same place but have different phone numbers. eg mobile phones?
One approach is to generate a set of unique phone, postal codes that are duplicates and then LEFT join your base set to the generated set where the postal_Code is null.
Select *
FROM SHEET1 A
LEFT JOIN (
Select count(*) as cnt pstl_Code, phone
From sheet1
group by pstl_Code, phone
having count(*) > 1) B
on A.Pstl_Code = B.Pstl_Code
and A.Phone = B.Phone
where B.pstl_Code is null and b.phone is null

How to split a single column into multiple columns in SQL Server select statement?

I am new to SQL Server . I have a single long column with names starting from a, b, c and d. I want to show them in separate columns of NameA, NameB, NameC and NameD. I tried union but it shows in one column. I tried case but I dont know how to use it. Please help.
Existing column
names
A1
B1
A2
C1
A3
A4
A_names| B_names | C_names
A1 | B1 | C1
A2
A3
A4
just for fun and curious why you want that:
select *
from
( select idx = left(names,1)
, names
, rn = row_number() over (partition by left(names,1) order by names)
from
( values ('A1'),('B1'),('A2'),('C1'),('A3'),('A4'),('B2'))
v(names)
) dat
pivot
( max(names)
for idx in ([A],[B],[C],[D])
) p
http://sqlfiddle.com/#!6/9eecb/4013/0
I don't think this is something that should be solved in SQL. It's a representational thing that should probably be done in the application.
However, if you insist to use SQL for this, this is how you could do it. The main problem with this query is that the ROW_NUMBER function will be quite bad for performance.
WITH nameA
(
SELECT name, ROW_NUMBER() OVER(ORDER BY name) AS rn
FROM t1
WHERE name LIKE 'a%'
), nameB AS
(
SELECT name, ROW_NUMBER() OVER(ORDER BY name) AS rn
FROM t1
WHERE name LIKE 'b%'
)
SELECT name FROM nameA
FULL OUTER JOIN nameB
ON nameA.rn = nameB.rn
ORDER BY nameA.rn,nameB.rn;
You can use CASE (https://msdn.microsoft.com/en-us/library/ms181765.aspx)
This Query should work:
SELECT
CASE WHEN users.name like 'a%' THEN users.name ELSE NULL END AS NameA,
CASE WHEN users.name like 'b%' THEN users.name ELSE NULL END AS NameB,
CASE WHEN users.name like 'c%' THEN users.name ELSE NULL END AS NameC,
CASE WHEN users.name like 'd%' THEN users.name ELSE NULL END AS NameD
FROM users
Look at this post, it is very close to your problem.
Itzik Ben-Gan | SQL Server Pro
This isn't really the way relational databases work. When you have data in the same row, it's supposed to be related in some way - a common ID, at the least. What is it that would connect the person whose name happens to begin with A to the person whose name happens to begin with B? Why would you ever want the RDBMS to make such an arbitrary connection?
If you have a requirement to display users in such a way, you'd just want to write several queries and have your presentation layer deal with laying them out properly, e.g.
SELECT name FROM users WHERE name LIKE 'a%'
SELECT name FROM users WHERE name LIKE 'b%'
SELECT name FROM users WHERE name LIKE 'c%'
etc...
The presentation layer could run each query and then populate a table appropriately. Even better would be to have the presentation layer just run this query:
SELECT name FROM users
And then appropriately sort and display the data, which is probably going to be less expensive than multiple scans on your users table by SQL Server.

Select all unique names based on most recent value in different field

I have an access database with a table called SicknessLog. The fields are ID, StaffName, [Start/Return], DateStamp.
When a member of staff is off work for sickness then a record is added to the table and the value in the [Start/Return] field is 1. When they return to work a new record is added with the same details except the [Start/Return] field is 0.
I am trying to write a query that will return all distinct staff names where the most recent record for that person has a value of 1 (ie, all staff who are still off sick)
Does anyone know if this is possible? Thanks in advance
Here's one way, all staff that has been sick where it does not exist an event after that where that staff is "nonsick":
select distinct x.staffname
from sicknesslog x
where Start/Return = 1
and not exists (
select 1
from sicknesslog y
where x.StaffName = y.StaffName
and y.DateStamp > x.DateStamp
and y.Start/Return = 0
)
You can use group by to achieve this.
select staffname ,max(datestamp) from sicknesslog where start/return = 1 group by staffname
it will return all latest recored for all staff. If ID column is autogenerated PK then you can use it in max function.
select staffname,MAX(datestamp)
from sicknesslog
where [start/return]=1
group by staffname
order by max(datestamp) desc,staffname
This will retrieve latest records who is sick and off to work
This should be close:
select s.StaffName, s.DateStamp, s.[Start/Return]
from SicknessLog s
left join (
select StaffName, max(DateStamp) as MaxDate
from SicknessLog
group by StaffName
) sm on s.StaffName = sm.StaffName and s.DateStamp = sm.MaxDate and s.[Start/Return] = 1

Kinda complex inner join and sum query

I am stuck with a query and would appreciate if you guys could help me.
We are using a table (MS Access) to store project plans for multiple companies as follows:
ID PROJECT_NAME COMPANY_NAME MILESTONE_NAME MILESTONE_TYPE
The objective of my query is to return the count of "applicable" rollouts.
A rollout is the unique combination of project and company. Example:
Project 1 being executed in the Company A
Project 2 being executed in the Company A
Project 1 being executed in the Company B
An applicable project is whatever project which it last milestone has a MILESTONE_TYPE different than "DUMMY".
An applicable rollout should look like this:
ID PROJECT_NAME COMPANY_NAME MILESTONE_NAME MILESTONE_TYPE
1 Project 3 Company D 6.2 Rollout Completed Applicable
In order to retrieve the last milestone of the project I am using the following SQL:
SELECT Sheet1.[PROJECT_NAME], MAX(Sheet1.[MILESTONE_NAME])
FROM Sheet1
INNER JOIN Sheet1 AS Sheet1_1 ON (Sheet1.[PROJECT_NAME] = Sheet1_1.[PROJECT_NAME])
AND (Sheet1.[MILESTONE_NAME] = Sheet1_1.[MILESTONE_NAME])
GROUP BY Sheet1.[PROJECT_NAME]
ORDER BY Sheet1.[PROJECT_NAME]
The expected result of the query I need your support would be:
PROJECT_NAME COUNT_OF_APPLICABLE_ROLLOUTS
Project A 5
Project B 6
However I have absolutely no idea how to even get started...
Does anyone know how to put in all in a SQL query?
Thanks in advance.
Assuming that bigger "id" means later, the following query returns information about the latest non-dummy row:
select p.*
from Sheet1.p join
(select project_name, company_name, max(id) as maxid
from Sheet1
where Milestone_Name <> 'Dummy'
group by project_name, company_name
) pc
on p.project_name, pc.company_name
(Note: I haven't tested this so it might have syntax errors.)
You can try this:
SELECT myTable.*
FROM (
SELECT DISTINCT COMPANY_NAME
FROM Sheet1
) CN
CROSS APPLY
(
SELECT TOP 1 *
FROM Sheet1 myTable2
WHERE myTable2.COMPANY_NAME = CN.COMPANY_NAME
ORDER BY
MILESTONE_NAME DESC
) myTable