Hopefully a fairly simple bit of SQL, I have a table with two columns, street and city. Given a list of 3 street names, how do I select the city which is common to the streets?
For example.
Street City
------ ----
1st St NYC
2nd St NYC
3rd St NYC
1st St SF
1st St LA
etc St XX
If I have "1st St", "2nd St" and "3rd St", which query returns "NYC"?
You can use group by and having:
select t.city
from table t
where t.street in ('1st st', '2nd st', '3rd st')
group by t.city
having count(distinct t.street) = 3;
This is an example of a set-within-sets query, where you are looking for sets of things (streets) for another thing (cities). Group by and having is a very flexible way of addressing this type of problem.
Related
Hope someone can help me with this. I am not great at SQL.
I want to get list of employees who has address in both USA and UK(England/Scotland)
Employee
Address
Emp1
England
Emp1
England
Emp1
Scotland
Emp2
US
Emp2
US
Emp2
Canada
Emp3
Scotland
Emp3
US
Emp3
Scotland
Emp3
US
Emp3
India
There can be multiple countries but i want to focus on US and UK(which includes both England and Scotland) only.
You can join the table with itself (one instance for US, one instance for UK) to find rows you want. For example:
select distinct us.employee
from t us
join t uk on uk.employee = us.employee
where us.address = 'US'
and uk.address in ('England', 'Scotland')
Alternatively, you can use EXISTS to filter out rows.
Using aggregation this is pretty straight forward.
Select Employee
from YourTable
where Address in ('England', 'Scotland')
group by Employee
having count(distinct Address) = 2
You can do this effectively by using a case that identifies every grouped nationality you need, then applying a COUNT DISTINCT, that does not take into account of nulls in the nationality column.
SELECT
Employee,
Address,
(CASE WHEN Address IN ('England', 'Scotland') THEN 'english'
WHEN Address IN ('US') THEN 'american'
ELSE NULL
END) AS nationality
FROM
table
GROUP BY
Employee
HAVING
COUNT(DISTINCT nationality) = 2
How to write regular expression for zipcode pattern? I need to makesure that all zipcodes(sample addresses) are 5 digits, but my query is not working.
with table1 as(
select "123 6th St. Melbourne, FL 32904" as address union all
select "71 Pilgrim Avenue, Chevy Chase, MD 20815" union all
select "70 Bowman St. South Windsor, CT 06074" union all
select "4 Goldfield Rd. Honolulu, HI 966815" union all
select "44 Shirley Ave. West Chicago, IL 60185" union all
select "514 S. Magnolia St. Orlando, FL 32806 "
)
select address,regexp_contains("address",r"\s\d{5}$")check from table1
At least remove quotes around address in regexp_contains
select address, regexp_contains(address, r"\s\d{5}$") check from table1
Also you might want to revisit use of $ at the end of regex
Consider r"\b\d{5}\b" as an option
I am trying to return results in TSQL where it only displays addresses where there are multiple names. The tricky part has been there are multiple duplicates already in this table... so the Having Count variations that I've tried do not work because they all have a count greater than one. So I have not been able to easily distinguish unique names that have the same address. The solution illustrated below is what I would like to produce... and I have but my solution is a sad last ditched effort within Access where I ended up using a query with three sub queries to get the results:
Address Name
101 1st Ave Brian Wood
101 1st Ave Amy Wood
101 1st Ave Adam Wood
555 5th St Sarah Parker
555 5th St Parker Corp.
Sample Data Looks Like this:
Address Name
101 1st Ave Brian Wood
101 1st Ave Brian Wood
101 1st Ave Brian Wood
101 1st Ave Amy Wood
101 1st Ave Adam Wood
555 5th St Sarah Parker
555 5th St Sarah Parker
555 5th St Sarah Parker
555 5th St Parker Corp.
I've been trying to get this for hours... I know their is a much simpler way to do this but as it's been a 16 hour day and it's 2:00 am I just can't get my head around it.
Here is an example of my best TSQL results... it does the trick but it bumps it into two different columns:
SELECT DISTINCT t1.Name, t2.Name, t1.Address
FROM tblLeads t1
JOIN tblLeads t2 ON t1.Address = t2.Address
WHERE t1.Name <> t2.Name
ORDER BY t1.Address
You can do a GROUP with COUNT(Distinct Name) > 1 to get Address with more than 1 unique name, and then do a select distinct with a filter on the above grouped Addresses like this.
SELECT DISTINCT Address,Name
From Table1
WHERE Address IN (
SELECT Address
FROM Table1
GROUP BY Address
HAVING COUNT(distinct Name) > 1
)
You could use multiple CTE's to simplify this task. You first want to clean up your data, so remove all those duplicates, therefore you can use DISTINCT. Then use Count(*)OVER(Partition By Address) to get the count of rows per Address:
WITH CleanedData AS
(
SELECT DISTINCT Address, Name
FROM dbo.tblLeads
),
CTE AS
(
SELECT Address, Name,
cnt = Count(*) OVER (Partition By Address)
FROM CleanedData
)
SELECT Address, Name
FROM CTE
WHERE cnt > 1
Demo
By the way, this works also if Address has null values: Demo (as opposed to this).
Use EXISTS to verify same addresses but other name:
SELECT DISTINCT t1.LastName, t1.Street
FROM tblLeads t1
WHERE EXISTS (select 1 from tblLeads t2
where t1.Street = t2.Street
and t1.LastName <> t2.LastName)
ORDER BY t1.Street
alternative solution to Tim's one without CTE:
select address, name
from (select t.*, count(*) over(partition by address) as cnt
from (select distinct address, name from tblLeads) t
) where cnt > 1
Quite often I have to solve the following problem. Suppose I have 3 columns: Col A, Col B, Col C.
Col A contain some date which I need group on. Col B contains value for which I need to find minimum for each group in Col A. And Col C contains data for which I would like to find where minimum occurred, that is pull value from Col C corresponding to min in Col B.
I commonly solve this problem, but writing JOIN statement. Does anybody know better solution, without JOIN? The problem seem so common to me that I would image it would make sense to create dedicated SQL command. It is like finding value of the function at a point of minimum (from math point of view)
Regards,
UPDATE.
I apologize for not posting an example of what I mean. Here is my table:
Location Quantity Street
New York 2 Broad
New York 3 Main
Pittsburgh 1 Grove
Pittsburgh 5 School
Austin 7 Hayes
Austin 2 Barn
I would like to group by "Location" and choose min in "Quantity" for each group. Finally I would like to find "Street" corresponding to each min value.
Here is how my final output should look like:
Location Quantity Street
Austin 2 Barn
New York 2 Broad
Pittsburgh 1 Grove
And here is how I accomplish it ( I believe it is too long and there should be dedicated SQL function for it)
SELECT TheFunction.Location, Quantity, Street
FROM [AnalysisDatabase].[dbo].[ValueAtMin] As TheFunction
inner join
(SELECT [Location], Min([Quantity]) as MinValue
FROM [AnalysisDatabase].[dbo].[ValueAtMin] Group by [Location]) as XValue
on TheFunction.Location = XValue.Location and XValue.MinValue = TheFunction.Quantity
This works with your dataset in mysql:
select location, quantity, street
from tempso c
where quantity = (select min(quantity)
from tempso b
where c.location = b.location)
order by location
Try this sql below:
Data table (using #temp)
location quantity Street
------------------------------ ----------- ------------------------------
New York 2 Broad
New York 3 Main
Pittsburgh 1 Grove
Pittsburgh 5 School
Austin 7 Hayes
Austin 2 Barn
SQL:
select location, quantity, street from #temp a
where quantity in (select min(quantity) as quantity from #temp b group by location having a.location = b.location)
order by location asc, quantity desc
Data Result:
location quantity street
------------------------------ ----------- ------------------------------
Austin 2 Barn
New York 2 Broad
Pittsburgh 1 Grove
In postgresql:
select
distinct on (a)
a,b,c
from tbl
order by a, b
You can also achieve it with a window function to figure out the correct c,
and then group by a (by putting the window query inside the grouping query)
Suppose I have one table with two column, Country and City.
Country
USA
Canada
UK
City
NY
London
I want to join/merge both column records and expect the output like this -
USA
Canada
UK
NY
London
So, what will be the SQL query to merge different columns records of same table?
SELECT Country FROM TABLE
UNION
SELECT City FROM Table
should do it.
Responding to the comment "I am searching for any quick way. Because if I need to merge 10 columns then i have to write 10 Unions! Is there any other way?":
You can use an unpivot, which means you just need to add the column names into a list. Only thing is to watch for data types though. eg:
--CTE for example only
;WITH CTE_Locations as (
select Country = convert(varchar(50),'USA'), City = convert(varchar(50),'NY')
union select Country = 'Canada', City = 'Vancouver'
union select Country = 'UK', City = 'Manchester'
)
--Select a list of values from all columns
select distinct
Place
from
CTE_Locations l
unpivot (Place for PlaceType in ([Country],[City])) u