Need Solution. 2 row into 1 row sql server 2008 - sql

This is my 2 normalize table which has Clientid into Telephone table
(ClientID int Primary key,
FName varchar(25),
LName varchar(25),
HomeAddress varchar(50))
CREATE TABLE Telephone
(TelephoneID tinyint IDENTITY(1,1)Primary key,
TelephoneNo int,
ClientID int foreign key references Client(ClientID))
so the values for my Client table..
ClientID | FName | LName | HomeAddress
1 marvin Biu p.guevarra st.
2 harry sendon cali st.
and into my Telephone table..
TelephoneID | TelephoneNo | ClientID
1 1234567 1
2 7654321 1
3 2222222 2
since it is possible to that a client has a multiple telephone no
so i would like to become like this..
ClientID | FName | LName | HomeAddress | Telephones
1 marvin Biu p.guevarra st. 1234567, 7654321
2 harry sendon cali st. 2222222
i only come up with the code like this
select distinct lname, CAST(telephoneno AS VARCHAR(10)) + ',' + CAST(telephoneno AS VARCHAR(10)) as Telephones
from telephone
left join client
on client.clientid = telephone.clientid
ended up like this..
LName | Telephones
Biu 1234567, 1234567
Biu 7654321, 7654321
sendon 2222222
Please anyone help, its ok that the table ended up in a simple form like above shown,
i really wanted the 1234567 telephoneno join with 7654321 telephoneno with coma in between in telephones column with one Lname "Biu" column. thats make 1 row. :/

SELECT
lname,
Telephones = STUFF((SELECT ','+ CAST(t.telephoneno AS VARCHAR(10))
FROM telephone t
WHERE t.clientid = c.clientid
For XML PATH('')
),1,1,'')
FROM client c

Always qualify your tables in a join, it makes it much clearer to see what's going on:
select distinct t.lname, CAST(t.telephoneno AS VARCHAR(10)) + ',' + CAST(c.telephoneno AS VARCHAR(10)) as Telephones
from telephone t
left join client c
on c.clientid = t.clientid

Related

SQL Lookup function

I have a Table that has employee info and another that has Manager assignments.
The manager info table references employee table by employee id in addition to managers.
I have been able to left join the table but I want to display the name rather than just employee ID.
SELECT CONCAT_WS(' ',[FirstName],[LastName]) AS FullName,
[EmployeeID]
,[Status]
,[LastName]
,[FirstName]
,[ManagersTbl].[ManagerIDf]
FROM [EmployeesTbl]
LEFT JOIN [ManagersTbl] on [EmployeesTbl].[EmployeeID] = [ManagersTbl].[EmployeeIDf]
WHERE Status = 'A'
Manager Table
_____________
| EmployeeIDf | ManagerIDf |
-----------------------------
001T | 005C
002J | 005C
_______________________________________________
Employee Table
______________
| EmployeeID | FirstName | LastName | Status |
-----------------------------------------------
001T | Tom | Spanks | A
002J | John | Doe | A
005C | Cruisin | Bruisin | A
_______________________________________________
End Result needed
_________________
|EmployeeID | StaffName | ManagerName |
------------------------------------------
001T | Tom Spanks | Crusin Bruisin
002J | John Doe | Crusin Bruisin
Please try this,
SELECT
EmployeeID
, CONCAT_WS(' ',A.[FirstName],A.[LastName]) AS StaffName
,CONCAT_WS(' ',B.[FirstName],B.[LastName]) AS ManagerName
FROM [EmployeesTbl] A
LEFT JOIN [ManagersTbl] M on A.[EmployeeID] = M.[EmployeeIDf]
LEFT JOIN [EmployeesTbl] B
ON M.[Manageridf]
=B.[EmployeeID]
WHERE Status = 'A'
There are numerous routes you can take, one possible solution is to join between your two tables to get your StaffName and then use an inline correlated subquery to get the ManagerName
select EmployeeId,
concat_ws(' ',FirstName,LastName) StaffName,
(select concat_ws(' ',FirstName,LastName) from EmployeeTable em where em.EmployeeID=m.ManagerIDf) ManagerName
from ManagerTable m join EmployeeTable e on e.EmployeeID=m.EmployeeIDf
where e.status='A'
you can use concatenation and join with two table by primary key employeeid.
concatenation function or + sign to concat in sql .

SQL Query Find Exact and Near Dupes

I have a SQL table with FirstName, LastName, Add1 and other fields. I am working to get this data cleaned up. There are a few instances of likely dupes -
All 3 columns are the exact same for more than 1 record
The First and Last are the same, only 1 has an address, the other is blank
The First and Last are similar (John | Doe vs John C. | Doe) and the address is the same or one is blank
I'm wanting to generate a query I can provide to the users, so they can check these records out, compare their related records and then delete the one they don't need.
I've been looking at similarity functions, soundex, and such, but it all seems so complicated. Is there an easy way to do this?
Thanks!
Edit:
So here is some sample data:
FirstName | LastName | Add1
John | Doe | 1 Main St
John | Doe |
John A. | Doe |
Jane | Doe | 2 Union Ave
Jane B. | Doe | 2 Union Ave
Alex | Smith | 3 Broad St
Chris | Anderson | 4 South Blvd
Chris | Anderson | 4 South Blvd
I really like Critical Error's query for identifying all different types of dupes. That would give me the above sample data, with the Alex Smith result not included, because there are no dupes for that.
What I want to do is take that result set and identify which are dupes for Jane Doe. She should only have 2 dupes. John Doe has 3, and Chris Anderson has 2. Can I get at that sub-result set?
Edit:
I figured it out! I will be marking Critical Error's answer as the solution, since it totally got me where I needed to go. Here is the solution, in case it might help others. Basically, this is what we are doing.
Selecting the records from the table where there are dupes
Adding a WHERE EXISTS sub-query to look in the same table for exact dupes, where the ID from the main query and sub-query do not match
Adding a WHERE EXISTS sub-query to look in the same table for similar dupes, using a Difference factor between duplicative columns, where the ID from the main query and sub-query do not match
Adding a WHERE EXISTS sub-query to look in the same table for dupes on 2 fields where a 3rd may be null for one of the records, where the ID from the main query and sub-query do not match
Each subquery is connected with an OR, so that any kind of duplicate is found
At the end of each sub-query add a nested requirement that either the main query or sub-query be the ID of the record you are looking to identify duplicates for.
DECLARE #CID AS INT
SET ANSI_NULLS ON
SET NOCOUNT ON;
SET #CID = 12345
BEGIN
SELECT
*
FROM #Customers c
WHERE
-- Exact duplicates.
EXISTS (
SELECT * FROM #Customers x WHERE
x.FirstName = c.FirstName
AND x.LastName = c.LastName
AND x.Add1 = c.Add1
AND x.Id <> c.Id
AND (x.ID = #CID OR c.ID = #CID)
)
-- Match First/Last name are same/similar and the address is same.
OR EXISTS (
SELECT * FROM #Customers x WHERE
DIFFERENCE( x.FirstName, c.FirstName ) = 4
AND DIFFERENCE( x.LastName, c.LastName ) = 4
AND x.Add1 = c.Add1
AND x.Id <> c.Id
AND (x.ID = #CID OR c.ID = #CID)
)
-- Match First/Last name and one address exists.
OR EXISTS (
SELECT * FROM #Customers x WHERE
x.FirstName = c.FirstName
AND x.LastName = c.LastName
AND x.Id <> c.Id
AND (
x.Add1 IS NULL AND c.Add1 IS NOT NULL
OR
x.Add1 IS NOT NULL AND c.Add1 IS NULL
)
AND (x.ID = #CID OR c.ID = #CID)
);
Assuming you have a unique id between records, you can give this a try:
DECLARE #Customers table ( FirstName varchar(50), LastName varchar(50), Add1 varchar(50), Id int IDENTITY(1,1) );
INSERT INTO #Customers ( FirstName, LastName, Add1 ) VALUES
( 'John', 'Doe', '123 Anywhere Ln' ),
( 'John', 'Doe', '123 Anywhere Ln' ),
( 'John', 'Doe', NULL ),
( 'John C.', 'Doe', '123 Anywhere Ln' ),
( 'John C.', 'Doe', '15673 SW Liar Dr' );
SELECT
*
FROM #Customers c
WHERE
-- Exact duplicates.
EXISTS (
SELECT * FROM #Customers x WHERE
x.FirstName = c.FirstName
AND x.LastName = c.LastName
AND x.Add1 = c.Add1
AND x.Id <> c.Id
)
-- Match First/Last name are same/similar and the address is same.
OR EXISTS (
SELECT * FROM #Customers x WHERE
DIFFERENCE( x.FirstName, c.FirstName ) = 4
AND DIFFERENCE( x.LastName, c.LastName ) = 4
AND x.Add1 = c.Add1
AND x.Id <> c.Id
)
-- Match First/Last name and one address exists.
OR EXISTS (
SELECT * FROM #Customers x WHERE
x.FirstName = c.FirstName
AND x.LastName = c.LastName
AND x.Id <> c.Id
AND (
x.Add1 IS NULL AND c.Add1 IS NOT NULL
OR
x.Add1 IS NOT NULL AND c.Add1 IS NULL
)
);
Returns
+-----------+----------+-----------------+----+
| FirstName | LastName | Add1 | Id |
+-----------+----------+-----------------+----+
| John | Doe | 123 Anywhere Ln | 1 |
| John | Doe | 123 Anywhere Ln | 2 |
| John | Doe | NULL | 3 |
| John C. | Doe | 123 Anywhere Ln | 4 |
+-----------+----------+-----------------+----+
Initial resultset:
+-----------+----------+------------------+----+
| FirstName | LastName | Add1 | Id |
+-----------+----------+------------------+----+
| John | Doe | 123 Anywhere Ln | 1 |
| John | Doe | 123 Anywhere Ln | 2 |
| John | Doe | NULL | 3 |
| John C. | Doe | 123 Anywhere Ln | 4 |
| John C. | Doe | 15673 SW Liar Dr | 5 |
+-----------+----------+------------------+----+

How to merge tables in SQL server that have a different column headers that map to a common description?

I have multiple tables that I want to merge into a single table. The tables represent the same data but have different column headers because they came from multiple sources. For example, in Table1 we will have "Tel_Nbr", in Table2 "TelNumber" and in Table3 "TelNum" etc.. Instead of renaming the columns in each table and for better maintainability, I figured I could create a mapping table where I map each column header name from each table to the common description in the final output table as shown below. However, I am not exactly sure that's the best approach because I am using the table names in the mapping table, and I cant figure out the query syntax.
Table1
First_Name | Last_Name | Telephone_Number
-----------------------------------------
John | Smith | 3333
Michael | Taylor | 4444
Table2
F_Name | L_Name | Tel_Nbr
--------------------------------
Joe | Lopez | 5555
Rachel | Moore | 6666
Mapping_Table
Output | Table1 | Table2
----------------------------------------
FirstName | First_Name | F_Name
LastName | Last_Name | L_Name
TelephoneNbr | Telephone_Number | Tel_Nbr
Output
FirstName | LastName | TelephoneNbr
-----------------------------------------
John | Smith | 3333
Michael | Taylor | 4444
Joe | Lopez | 5555
Rachel | Moore | 6666
As Gordon Linoff points out, what you ask for requires dynamic SQL. That is, build a query string from the content of mapping_table, then executing it.
Consider:
declare
#q1 nvarchar(max),
#q2 nvarchar(max),
#q nvarchar(max)
;
select
#q1 = string_agg(table1 + ' as ' + output, ', ') within group(order by output),
#q2 = string_agg(table2, ', ') within group(order by output)
from mapping_table;
set #q = 'select ' + #q1 + N' from table1 union all select ' + #q2 + ' from table2'
--debug
select #q;
-- execute
EXEC sp_executesql #q;
For your sample data, the generated query is (I added line breaks and indentation for better readibility):
select First_Name as FirstName, Last_Name as LastName, Telephone_Number as TelephoneNbr
from table1
union all
select F_Name, L_Name, Tel_Nbr from table2
Demo on DB Fiddle

Pick exact records

INSERT INTO filerecord (fname,
lname,
transdate,
memberid)
VALUES ('tyler',
'smith',
TO_DATE ('07/01/2016', 'mm/dd/yyyy'),
'111');
I get the following result:
fname lname email
fernando hernandez fh#yahoo.com
fernando hernandez ts#hotmail.com
IT should not display Tyler Smith's Name & Email due to the transdate clause. I am looking for someone to get me only the Fernando Result.
I cannot change the structure of the tables.
You are getting a Cartesian product.
You have two entries with memberid = '111' in both tables, so this condition
AND b.memberid = e.memberid
filters you down to 4 rows --
one with Tyler Smith joined to Tyler Smith's email
one with Fernando Hernandez joined to Fernando Hernandez's e-mail,
one with Tyler Smith joined to Fernando Hernandez's email and
one with Fernando Hernandez joined to Tyler Smith's email
Then, this condition:
AND b.transdate >= TO_DATE ('07/02/2016', 'mm/dd/yyyy');
excludes two of those but not the other two.
You need a better data model and/or a more exact way to join your two tables.
In general, anytime you join two tables, one of the tables should have all of its primary key columns specified to avoid this type of error. (There are exceptions to that, as always).
It is not. I just created a new table and checked.
Table member
create table member (programid varchar(10), memberid int, fname varchar(10), lname varchar(10), email varchar(25))
Content
+-----------+----------+----------+-----------+----------------+
| PROGRAMID | MEMBERID | FNAME | LNAME | EMAIL |
+-----------+----------+----------+-----------+----------------+
| BLUE | 111 | tyler | smith | ts#hotmail.com |
| GREEN | 111 | fernando | hernandez | fh#yahoo.com |
+-----------+----------+----------+-----------+----------------+
Table filerecord
create table filerecord (fname varchar(10), lname varchar(10), transdate date, memberid int);
Content
+-------+-------+-----------+----------+
| FNAME | LNAME | TRANSDATE | MEMBERID |
+-------+-------+-----------+----------+
| tyler | smith | 7/1/2016 | 111 |
+-------+-------+-----------+----------+
Last Query
SELECT b.fname, b.lname, e.email
FROM filerecord b, member e
WHERE b.memberid IN ('111')
AND b.memberid = e.memberid
AND b.transdate >= TO_DATE ('07/02/2016', 'mm/dd/yyyy');
Result -
no rows selected.
Since memberid is not a unique identifier, there no reason to expect good things from a join condition like b.memberid = e.memberid.
Instead, you seem to suggest (or believe) that (memberid, fname, lname) should be a unique identifier. So, use it in the join condition:
... WHERE ... AND b.memberid = e.memberid
AND b.fname = e.fname
AND b.lname = e.lname
...
Like so:
SQL> SELECT b.fname, b.lname, e.email
2 FROM filerecord b, member e
3 WHERE b.memberid IN ('111')
4 AND b.memberid = e.memberid
5 AND b.fname = e.fname
6 AND b.lname = e.lname
7 AND b.transdate >= TO_DATE ('07/02/2016', 'mm/dd/yyyy');
FNAME LNAME EMAIL
-------------------- -------------------- --------------------
fernando hernandez fh#yahoo.com
1 row selected.

How to retrieve names within a column if values in another column corresponds to the primary key of desired name

I have a table in t-sql which looks like this
personid | firstname | lastname | managerid
1 | Tom | Bricks | null
2 | Joe | Liam | 1
3 | Mary | Hattan | 2
I am trying to query out a table like this:
Name | ManagerName
Tom | No manager
Joe | Tom
Mary | Joe
I can't seem to figure out way how to query the second column out my query as it stands is like this :
SELECT 'firstname' + ' ' + 'lastname' AS 'Name
Anyone got any idea?
You can use Self Join to get data using two column link on the same table.
Try this
SELECT t1.firstname as Name, ISNULL(t2.firstname,'No manager') as ManagerName
FROM tblName t1
LEFT JOIN tblName t2
ON t1.managerid = t2.personid
DEMO
You can do this by recursive CTE:
DECLARE #t TABLE
(
personid INT ,
firstname NVARCHAR(MAX) ,
lastname NVARCHAR(MAX) ,
managerid INT
)
INSERT INTO #t
VALUES ( 1, 'Tom', 'Bricks', NULL ),
( 2, 'Joe', 'Liam', 1 ),
( 3, 'Mary', 'Hattan', 2 );
WITH cte
AS ( SELECT personid ,
firstname ,
lastname ,
managerid
FROM #t
WHERE ManagerID IS NULL
UNION ALL
SELECT t.personid ,
t.firstname ,
t.lastname ,
t.managerid
FROM #t t
INNER JOIN cte ecte ON ecte.personid = t.ManagerID
)
SELECT *
FROM cte
GO
Output:
personid firstname lastname managerid
1 Tom Bricks NULL
2 Joe Liam 1
3 Mary Hattan 2