SQL Query that can return intersecting data - sql-server

I have a hard time finding a good question title - let me just show you what I have and what the desired outcome is. I hope this can be done in SQL (I have SQL Server 2008).
1) I have a table called Contacts and in that table I have fields like these:
FirstName, LastName, CompanyName
2) Some demo data:
FirstName LastName CompanyName
John Smith Smith Corp
Paul Wade
Marc Andrews Microsoft
Bill Gates Microsoft
Steve Gibbs Smith Corp
Diane Rowe ABC Inc.
3) I want to get an intersecting list of people and companies, but companies only once. This would look like this:
Name
ABC Inc.
Bill Gates
Diane Rowe
John Smith
Marc Andrews
Microsoft
Smith Corp
Steve Gibbs
Paul Wade
Can I do this with SQL? How?

You take all the person names, and then also add all the companies
SELECT CONCAT([First Name],' ',[Last Name]) AS Name FROM Contacts
UNION ALL
SELECT DISTINCT CompanyName FROM Contacts
WHERE CompanyName IS NOT NULL
The DISTINCT keyword ensures that companies are output only once, and the WHERE
clause removes rows where no company info is known.
If a person has the same name as a company, then this will output a duplicate. If you don't want that, then change UNION ALL to UNION, and any name will be output only once.

I'm not sure what you mean by "intersecting," but you can easily get the results you describe as the union of two queries against that same table.
select
t.firstname + ' ' + t.lastname
from
mytable t
union
select
t.company
from
mytable t
Edit: UNION should make each SELECT distinct by default.

Does this do what you need?
SELECT FirstName + ' ' + LastName AS Name
FROM Contacts
UNION
SELECT CompanyName
FROM Contacts
(The UNION rather than UNION ALL will ensure distinctness of both top and bottom parts. mdma's answer will work if you do need the possibility of duplicate people names. You might need to add an ORDER BY Name depending on your needs)

Related

SQL Get row that have maximum values over two columns

I have a table like this in Snowflake. It supports ANSI SQL, so don't worry if this DB isn't familiar to you.
Salesman
Customer
Country
Brown
Super Company
UK
Brown
Another customer
UK
Smith
Contoso
US
Brown
Test company
US
I'd need to find where each salesman have most of customers. So desired response for the query would be like this.
Salesman
Country
cnt(country)
Brown
UK
2
Smith
US
1
I've come up with this
SELECT
salesman,
country,
max(count(country))
FROM
customertable
GROUP BY
salesman, country
But nested aggeregation functions aren't supported. And I've already read quite good reasons for that. But I just cannot find a way to do that in any other way.
QUALIFY could be used to filter the highest value per salesman:
SELECT salesman,
country,
count(country) AS cnt
FROM customertable
GROUP BY salesman, country
QUALIFY RANK() OVER(PARTITION BY salesman ORDER BY cnt DESC) = 1
Regarding your questions i guess you would want to count customer by country instead of country.
This should do the job with the use of WINDOW FUNCTIONS AND QUALIFY
Window Functions documentation
CREATE OR REPLACE TABLE customers (salesman STRING, customer STRING, country STRING);
INSERT INTO customers
VALUES
('Brown', 'Super Company', 'UK'),
('Brown', ' Another customer', 'UK'),
('Smith', 'Contoso', 'US'),
('Brown', 'Test company', 'US')
;
SELECT
salesman,
country,
COUNT(customer) AS nb_customer
FROM customers
GROUP BY
salesman,
country
QUALIFY RANK() OVER (PARTITION BY salesman ORDER BY nb_customer DESC) = 1
;

Script for incrementally creating records

Paul provided a useful script for the issue below but I would like to actually effect the changes. I can only see it if I use the select statement
Please help with this one
Table name: Citizen
Firstname Lastname Telephone Many other columns......
John Smith 03907625212
Andrew Evans 0807452132
Bill Towny 05907122139
Dame Beaut 07894650569
I have over 150,000 records where the Telephone number needs to be adopted to a set format (set telephone area code and in incremental order) ie 01907000001, 01907000002 as shown below. There are other columns asides the firstname and lastname which will all remain unchanged..only telephone field requires this transformation.
It should ideally look like this:
Firstname Lastname Telephone Many other columns......
John Smith 01907000001
Andrew Evans 01907000002
Bill Towny 01907000003
Dame Beaut 01907000004
I will really appreciate some help or guidance on this.
Try something like this:
SELECT
[FirstName],
[LastName],
'01907' + --area code
RIGHT('00000' + --middle padding for zero's
CAST(ROW_NUMBER() OVER (ORDER BY [LastName]) AS VARCHAR) --incremental value
,6) AS 'Telephone' --6 characters plus area code
--<< YOUR OTHER FIELDS
FROM
[AdventureWorks].[Person].[Person]
I used Adventure Works just to test it.
Change the ORDER BY clause in the windowing function if you want it to increment by something else.

SQL Server 2008 similar to group_concat topic fill distinct colums from two separate tables

Sorry... first time here and amateur...
I have two different tables (contact_data_a and contact_data_b) from two different divisions as follows:
contact_data_a
id customer contact
11200 Müller KG Hans
11201 Huber GmbH Patrick
11203 Gruber GmbH Manu
11205 Meyer GmbH Manu
contact_data_b
id customer contact
11200 Müller E. Peter
11202 Schubert AG Louis
11204 E.Schmidt Louis
11205 Mayer GmbH Peter
What I would like to have in the end is something like this:
contact_data_all
id customer contact_a contact_b
11200 Müller KG Hans Peter
11201 Huber GmbH Patrick 0
11202 Schubert AG 0 Louis
11203 Gruber GmbH Manu 0
11204 E. Schmidt 0 Louis
11205 Meyer GmbH Manu Peter
"id" is clear and distinct, but names in column "customer" might vary (incl. misspellings). This is no problem. Information could come from either table. My problem are the contact columns. Contacts from list contact_data_a should appear in column contact_a (or Null if they do not exist) and contacts from list contact_data_b should appear in column contact_b (or Null).
A friend said I might use
`SELECT id, customer, GROUP_CONCAT(contact_a) as contact_a,GROUP_CONCAT(contact_b) as contact_b FROM
(SELECT id, customer, contact_a, null as contact_b FROM contact_data_a
UNION
SELECT id, customer, null as contact_a, contact_b FROM contact_data_b)
GROUP BY id ORDER BY id`
But I only have SQL 2008, so CONCAT is not available yet.
Thank you in advance for any help or idea!!!
Try this one -
SELECT
id
, customer
, MAX(contact_a) AS contact_a
, MAX(contact_b) AS contact_b
FROM (
SELECT id, customer, contact_a, '0' AS contact_b
FROM contact_data_a
UNION ALL
SELECT id, customer, '0' AS contact_a, contact_b
FROM contact_data_b
) t
GROUP BY id, customer
ORDER BY id

sql conversions in select statement

Here is a table example. using sql-server
I am trying to pull the max(login date) for each employee below, but the "login date" in the database is datatype int.
I can select it easy enough, ie,
select employee,title,max(login_date) from employee group by employee,title
I can use substring to convert the login_date("YYYYMM") to a date variable,
set #var_year=select (substring((select login_date),1,4))
using a variable to store the year and a variable to store the month, but how do I pass that to my main select statement?
Employee Title Login_Date
-----------------------------------------
Mike VP 201301
Amy CEO 201201
Joe Office Mgr 201105
Andy Admin Asst 201308
Joe Office Mgr 201205
Andy Admin Asst 201309
Joe Office Mgr 201205
Andy Admin Asst 201309
A few ways you could do that.
One would be
Select m.employee,m.title,
convert(int,substring(thisisNOTadate,1,4)) as [Year],
convert(int,substring(thisisNOTadate,5,2)) as [Month]
From
(select employee,title,max(login_date) as ThisisNOTadate
from employee group by employee,title
) m
Personally after slapping who ever called a string in the format YYYYMM login_date a few times, I'd rework the table so login_date was in fact a date with something like Convert(DateTime,Convert(VarChar(6), Login_date) + '01'), and then anything that needed parts of the date could use that standard date functions.
So based on your comment to Mr ReBand earlier then
select employee,title,
max(convert(datetime,Convert(varchar(6),login_date) + '01')) as arealdate
From employee group by employee,title
would be another.

T-SQL How To: Compare and List Duplicate Entries in a Table

SQL Server 2000. Single table has a list of users that includes a unique user ID and a non-unique user name.
I want to search the table and list out any users that share the same non-unique user name. For example, my table looks like this:
ID User Name Name
== ========= ====
0 parker Peter Parker
1 parker Mary Jane Parker
2 heroman Joseph (Joey) Carter Jones
3 thehulk Bruce Banner
What I want to do is do a SELECT and have the result set be:
ID User Name Name
== ========= ====
0 parker Peter Parker
1 parker Mary Jane Parker
from my table.
I'm not a T-SQL guru. I can do the basic joins and such, but I'm thinking there must be an elegant way of doing this. Barring elegance, there must be ANY way of doing this.
I appreciate any methods that you can help me with on this topic. Thanks!
---Dan---
One way
select t1.* from Table t1
join(
select username from Table
group by username
having count(username) >1) t2 on t1.username = t2.username
The simplest way I can think of to do this uses a sub-query:
select * from username un1 where exists
(select null from username un2
where un1.user_name = un2.user_name and un1.id <> un2.id);
The sub-query selects all names that have >1 row with that name... outer query selects all the rows matching those IDs.
SELECT T.*
FROM T
, (SELECT Dupe_candidates.USERNAME
FROM T AS Dupe_candidates
GROUP BY Dupe_candidates.USERNAME
HAVING count(*)>1
) Dupes
WHERE T.USERNAME=Dupes.USERNAME
You can try the following:
SELECT *
FROM dbo.Person as p1
WHERE
(SELECT COUNT(*) FROM dbo.Person AS p2 WHERE p2.UserName = p1.UserName) > 1;

Resources