SQL Max and Sum - sql

Below is my query that I am using:
SELECT
County,
Code,
Sum(PaidAmount) AS TotalPaid
FROM
Counties
GROUP BY
County,
Code
It returns the set:
County Code TotalPaid
Brown 99 210.21
Lyon 73 322.22
Lyon 88 533.22
Lincoln 22 223.21
What I am looking for is a query that will return the rows that show the County and the Code for the Max TotalPaid for each County. An example of the result set that I need is shown below (notice that Lyon, 73 is removed since Lyon, 88 has a higher TotalPaid amount):
County Code TotalPaid
Brown 99 210.21
Lyon 88 533.22
Lincoln 22 223.21

I wasn't able to test this, but RANK should solve this:
SELECT x.County, x.Code x.TotalPaid
,RANK() OVER
(PARTITION BY x.County ORDER BY x.TotalPaid DESC) AS 'RANK'
FROM
(SELECT
County,
Code,
Sum(PaidAmount) AS TotalPaid
FROM
Counties
GROUP BY
County,
Code) x
WHERE Rank = 1

I think you need to do something like the follwoing. I've just been called away before I could review what I've written but hopefully it will give you enough of a pointer. Some RDBMSes won't allow the "where country, TotalPaid = select value, value" construct but you can work around this
select
County,
Code,
TotalPaid
from (SELECT
County,
Code,
Sum(PaidAmount) AS TotalPaid
FROM
Counties
GROUP BY
County,
Code ) tbl
where County, TotalPaid = (select County,
max(TotalPaid)
FROM
Counties
GROUP BY
County,
Code ) tbl2

SELECT
c.County,
c.Code,
Sum(c.PaidAmount) AS TotalPaid
FROM
Counties c
WHERE
c.Code in (select max(c2.code) from counties c2 where c2.county = c.county)
GROUP BY
c.County,
c.Code
this one should work although i haven't tested

You'll have to use windowing functions to do this. While what you want is easily expressed in english, it's not easily expressed in SQL, unfortunately. This should do what you need:
select
County, Code, TotalPaid
from
(
SELECT
County,
Code,
sum(PaidAmount) AS TotalPaid
FROM
Counties
GROUP BY
County, Code
) source
where (row_number() over (partition by County order by TotalPaid desc)) = 1

Here's an updated solution:
select c1.county, c1.code, c1.paidAmount
from counties c1
inner join (
select county, max(paidAmount) paidAmount
from counties
group by county) c2
on c1.county=c2.county and c1.paidAmount=c2.paidAmount;
Note, if there are multiple max payments for a certain county, this will return all rows that share that maximum.

Related

How to get values of one column without the aggregate column?

I have this table:
first_name
last_name
age
country
John
Doe
31
USA
Robert
Luna
22
USA
David
Robinson
22
UK
John
Reinhardt
25
UK
Betty
Doe
28
UAE
How can I get only the names of the oldest per country?
When I do this query
SELECT first_name,last_name, MAX(age)
FROM Customers
GROUP BY country
I get this result:
first_name
last_name
MAX(age)
Betty
Doe
31
John
Reinhardt
22
John
Doe
31
But I want to get only first name and last name without the aggregate function.
If window functions are an option, you can use ROW_NUMBER for this task.
WITH cte AS (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY country ORDER BY age DESC) AS rn
FROM tab
)
SELECT first_name, last_name, age, country
FROM cte
WHERE rn = 1
Check the demo here.
It sounds like you want to get the oldest age per country first,
SELECT Country, MAX(age) AS MAX_AGE_IN_COUNTRY
FROM Customers
GROUP BY Country
With that, you want to match that back to the original table (aka a join) to see which names they match up to.
So, something like this perhaps:
SELECT Customers.*
FROM Customers
INNER JOIN
(
SELECT Country, MAX(age) AS MAX_AGE_IN_COUNTRY
FROM Customers
GROUP BY Country
) AS max_per_country_query
ON Customers.Country = max_per_country_query.Country
AND Customers.Age = max_per_country_query.MAX_AGE_IN_COUNTRY
If your database supports it, I prefer using the CTE style of handling these subqueries because it's easier to read and debug.
WITH cte_max_per_country AS (
SELECT Country, MAX(age) AS MAX_AGE_IN_COUNTRY
FROM Customers
GROUP BY Country
)
SELECT Customers.*
FROM Customers C
INNER JOIN cte_max_per_country
ON C.Country = cte_max_per_country.Country
AND C.Age = cte_max_per_country.MAX_AGE_IN_COUNTRY

How do I find a duplicate in SQL

I have a query that selects 3 columns. Each row row should be a unique combination of county, city,and zip. However, I have reason to believe I'm getting a duplicate somewhere. How do I find the duplicate ? COUNT() ?? This in MS SQL Server . Any help would be most appreciated. --Jason
SELECT COUNTY, CITY, ZIP
FROM MoratoriumLocations
WHERE MoratoriumID=20
ORDER BY County
You coul use group by and having
SELECT COUNTY, CITY, ZIP
FROM MoratoriumLocations
WHERE MoratoriumID=20
GROUP BY COUNTY, CITY, ZIP
HAVING COUNT(1) >1
ORDER BY County
If you want to get the full row details you can use a sub query in combination with the group by and having statements
SELECT x.*
FROM MoratoriumLocations x
INNER JOIN(
SELECT COUNTY, CITY, ZIP
FROM MoratoriumLocations
WHERE MoratoriumID=20
GROUP BY COUNTY, CITY, ZIP
HAVING COUNT(1) >1
) dups ON dups.County = x.County
AND dups.City = x.City
AND dups.Zip = x.Zip
See Preben's answer for how to find dups.
To avoid dups altogether consider creating an unique index.
I would suggest window functions:
SELECT ml.*
FROM (SELECT ml.*, COUNT(*) OVER (PARTITION BY County, City, Zip) as cnt
FROM MoratoriumLocations ml
WHERE MoratoriumID = 20
) ml
ORDER BY cnt DESC, County, City, Zip;
This will show the complete rows with duplicates, which can help you understand them better.

SQL find repeated values

I need to identify rows where a certain value is repeated. Here is a sample table:
COUNTRY CITY
Italy Milan
Englad London
USA New York
Canada London
USA Atlanta
The query should return...
COUNTRY CITY
Englad London
Canada London
...because London is repeated. Thank you in advance for your help.
The easiest way is to use a subquery that counts the number of times each city appears (and filter to those values that appear more than once):
SELECT * FROM Cities
WHERE City in
(
SELECT City FROM Cities
GROUP BY City
HAVING COUNT(*) > 1
)
If your DBMS supports windowed aggregates.
SELECT COUNTRY,
CITY
FROM (SELECT COUNTRY,
CITY,
COUNT(*) OVER (PARTITION BY CITY) AS Cnt
FROM Cities) T
WHERE Cnt > 1
SQL Fiddle
select country, city
from aTable
where city in
(
select city
from aTable
group by city
HAVING count(1) > 1
)
Try it here: http://sqlfiddle.com/#!3/e9b1a/1
Or if the same city & country combo appears twice and you're only interested where the countries are different:
select distinct country, city
from aTable
where city in
(
select city
from aTable
group by city
HAVING count(distinct country) > 1
)
Try it here: http://sqlfiddle.com/#!3/2dfaa/2
This one works. Got it from my wife (she finally had time to look into this). Thought you might be interested.
SELECT * FROM Cities
WHERE City in ( select city
from (SELECT City,
count(distinct country)
FROM Cities
GROUP BY City
HAVING count(distinct country) > 1) a )

Oracle Sql query Group by Clause

MY_TABLE = Table with 2 columns Number, City.
Desired Output = City and count of unique Number associated to the city. Seattle, Bellevue is part of Combined. Even though there are 4 numbers associated to Seattle, Bellevue the output is 3 as there are only 3 distinct numbers - 123, 456, 786.
MY_TABLE
Number City
123 Seattle
456 Bellevue
789 LosAngeles
780 LosAngeles
123 Bellevue
786 Bellevue
Desired Output:
Combined 3
LosAngeles 2
Query so far:
SELECT NUMBER, CITY FROM MY_TABLE WHERE LOOKUP_ID=100 AND CITY IN
('Seattle', 'Bellevue', 'LosAngeles')
GROUP BY NUMBER, CITY
Would highly appreciate if anyone provides a recommendations around the same.
You could do something like
SELECT (case when city IN ('Seattle', 'Bellevue')
then 'Combined'
else city
end) city,
count( distinct number )
FROM my_table
WHERE lookup_id = 100
AND city IN ('Seattle', 'Bellevue', 'LosAngeles')
GROUP BY (case when city IN ('Seattle', 'Bellevue')
then 'Combined'
else city
end)
Of course, my guess is that you have some other table that tells you which CITY values need to be combined rather than having a hard-coded CASE statement.
with t as (
SELECT (
case when city IN ('Seattle', 'Bellevue')
then 'Combined'
else city
end
) city, number from my_table
)
select city, count(distinct number) from t
group by city
Tell please, if it was useful
Try this:
SELECT
(CASE CITY
WHEN 'Seattle' THEN ‘Combined’
WHEN 'Bellevue' THEN ‘Combined’
ELSE CITY
END), COUNT(*)
FROM
MY_TABLE
WHERE
LOOKUP_ID=100 AND CITY IN ('Seattle', 'Bellevue', 'LosAngeles')
GROUP BY
NUMBER,
(CASE CITY
WHEN 'Seattle' THEN ‘Combined’
WHEN 'Bellevue' THEN ‘Combined’
ELSE CITY
END)
that should do what you asked for, but I suspect that you have some other tables where you define which cities should be considered the same, in such a case you'll need to join on those tables
There are 3 answers already and none of them are generic for more cities.
Try this:
SELECT City, COUNT(Number) AS ExclusiveNumbers
FROM (SELECT q2.City, q2.CityNumCount, b.Number
FROM MY_Table b INNER JOIN
(SELECT c.City, MAX(NumOccurs) AS CityNumCount
FROM My_Table c INNER JOIN
(SELECT Number, COUNT(City) AS NumOccurs
FROM My_Table
GROUP BY Number) q1 ON c.Number = q1.Number
GROUP BY c.City) q2 ON b.City = q2.City) q3
WHERE CityNumCount = 1
GROUP BY City
UNION
SELECT 'Combined', COUNT(DISTINCT Number)
FROM (SELECT q2.City, q2.CityNumCount, b.Number
FROM MY_Table b INNER JOIN
(SELECT c.City, MAX(NumOccurs) AS CityNumCount
FROM My_Table c INNER JOIN
(SELECT Number, COUNT(City) AS NumOccurs
FROM My_Table
GROUP BY Number) q1 ON c.Number = q1.Number
GROUP BY c.City) q2 ON b.City = q2.City) q3
WHERE CityNumCount > 1
The top half of the union works out, for each City name that has no numbers in common with any other city, how many different numbers it has.
The bottom half works out the count of different numbers for cities that do have numbers in common with other cities. These 2 figures will always add up to the count of distinct numbers in the original table.

Group By query - any other way?

I have the following table that contains the following data:
http://img513.imageshack.us/img513/9039/mycities.png
The CREATE statement and the inserts are at http://snipt.org/xoKl .
The table is a list of cities and each city belongs to a region and a country and each city has a founding date. The goal here is to get for each "Country / Region" pair a list of the oldest cities. We need the oldest city on the east coast of Canada, the oldest city on the west coast of the U.S and so on ...
The query that I use right now is:
SELECT * FROM MyCities
INNER JOIN
(SELECT Country, Region, MIN(FoundingDate) AS CityFoundingDate
FROM MyCities
GROUP BY Country, Region ) AS subquery
ON subquery.CityFoundingDate = MyCities.FoundingDate
AND MyCities.Country = subquery.Country
AND MyCities.Region = subquery.Region
I just want to know whether there are other ways to write this group by query or not. :-)
Is this query efficient or not?
Looking forward to a discussion.
What about?
select country, region, city from MyCities mc1
where foundingDate <= ALL (
select foundingDate from MyCities as mc2
where mc1.country = mc2.country and mc1.region = mc2.region
)
How about something like this?
Should work in Oracle (although I can't test it right now)
SELECT country, region, city, foundingdate
FROM (
SELECT country, region, city, foundingdate, MIN(founding_date) OVER PARTITION BY (country, region) min_date
FROM mycities) WHERE foundingdate=min_date
But what if there are two cities founded on the same year in the same country/region?