Display individual rows when count > x - mysql

I have a database with record_number(PRIMARY), owner_name, address in it.
I want to identify owner_name who own more than one property, and list each property owned by owner_name.
Something like:
record_number | owner_name | address
1 | Smith | 123 Main
7 | Smith | 1 Some Street
12 | Smith | 77 Dude Ln
19 | Jones | Some address
21 | Jones | Some Different address
47 | Jones | Yet another address
106 | Davis | You're getting the idea?
139 | Davis | All of these are different!
141 | Davis | They keep changing
158 | Davis | When will it end?

select record_number, owner_name, address
from your_table
where owner_name in
(
select owner_name
from your_table
group by owner_name
having count(*) > 1
)
order by owner_name, record_number

Related

How to wrap around from 10 to 1 in MySQL query?

I have a total number of 10 employees and I have to display the next 3 employees details on my page and I tried the below code.
SELECT *
FROM employee
where empid > 1
and is_active = 1
order
by empid ASC
limit 0 , 3
and I am getting the output 2,3,4 which is correct.
Now my issue is, If the empid is 10 then I am getting the empty row. Is it possible to display the 1,2,3 when the empid is 10 or if the empid is 8 the display 9,10,1
I mean I want it to wrap around from 10 to 1.
empid | Name | Position | Office | Age
1 | Airi | Accountant | Tokyo | 33
2 | Angelica | Officer | London | 47
3 | Ashton | Technical | Francisco| 66
4 | Bradley | Software | London | 41
5 | Brenden | Engineer | Francisco| 28
6 | qodjf | Accountant | Tokyo | 33
7 | Angelica | Officer | New York | 50
8 | Ashton | Technical | Francisco| 30
9 | zxysz | Software | London | 50
10 | Brenden | Engineer | Francisco| 28
I tried to create a table in db-fiddle but I am getting the error. I am using PHPMyAdmin. So i added table here.
Move the condition empid > ? DESC in the ORDER BY clause:
SELECT *
FROM employee
WHERE is_active = 1
ORDER BY empid > ? DESC, empid LIMIT 3
See the demo.

How can I return each record associated with State and City while returning State and City name only once? (MySql)

I'm not really sure how to ask this and I've been search-engining for awhile and haven't come up with anything useful.
Say I have the following three tables People, Cities and States:
PeopleID | Name | Age | CityIDFK
--------------------------------------------
1 | John | 24 | 20
2 | Jim | 28 | 21
3 | Joan | 49 | 10
4 | Mike | 37 | 10
5 | Bruce | 26 | 2
6 | Peter | 22 | 20
7 | Oprah | 27 | 3
7 | Jake | 21 | 1
CityIDPK | City | StateIDFK
---------------------------------------
1 | Seattle | 1
2 | Gotham | 2
3 | Oakland | 4
10 | Boise | 5
20 | Austin | 6
21 | Tyler | 6
StateIDPK | StateName
----------------------------
1 | Washington
2 | New York
3 | Oregon
4 | California
5 | Idaho
6 | Texas
How can I achieve the following output:
StateName | City | Name
---------------------------------------
California | Oakland | Oprah
Idaho | Boise | Mike
| | Joan
New York | Gotham | Bruce
Washington | Seattle | Jake
Texas | Austin | John
| | Peter
| Tyler | Jim
I'm not sure if the above output is possible or not, I would probably just do something like this:
SELECT StateName, City, Name FROM People
INNER JOIN Cities
ON Cities.CityIDPK = People.CityIDFK
INNER JOIN States
ON States.StateIDPK = Cities.StateIDFK
But that would return the StateName and City for every person, instead of just once.
StateName | City | Name
---------------------------------------
California | Oakland | Oprah
Idaho | Boise | Mike
Idaho | Boise | Joan
New York | Gotham | Bruce
Washington | Seattle | Jake
Texas | Austin | John
Texas | Austin | Peter
Texas | Tyler | Jim
If the output I want to achieve is possible, would someone show me an example of how to write the query, or point me in the right direction?
I agree with Tim, this should be handled in your presentation layer.
But you can do it if you're using MySQL 8 by taking advantage of window functions. We can use row_number() to determine the first row per state and per city, then use a case to only display the name for the first row.
SELECT
case row_number() over states_w
when 1 then states.name
else '' end as StateName,
case row_number() over cities_w
when 1 then cities.name
else '' end as CityName,
people.name as Name
FROM People
INNER JOIN Cities ON Cities.id = People.City_id
INNER JOIN States ON States.id = Cities.state_id
window states_w as (partition by states.id),
cities_w as (partition by cities.id);
If you're using MySQL before 8... upgrade. If you can't upgrade, it can be emulated.

Left join rows and right table rows in same column

I have two tables (Manager and Worker). I want to do a left join from Manager to Worker. The name of workers under a manager should come below manager name. The expected output is presented below:-
Manager Table:
ManagerCode Name Age
1 Chris 52
2 Rick 55
3 David 50
Worker Table
ManagerCode WName Age
1 Harry 33
1 Phil 40
2 Johnny 28
2 Jeff 47
Expected table:
ManagerCode Name Age
1 Chris
1 Harry
1 Phil
2 Rick
2 Johnny
2 Jeff
3 David
Left join results both manager and worker names side by side. But I want them in one column.
You meed UNION ALL and not a join:
select t.managercode, t.name, t.age
from (
select managercode, name, age, 1 as ismanager from Manager
union all
select managercode, wname, age, 0 from Worker
) t
order by t.managercode, t.ismanager desc
The column ismanager is used to sort the manager before all the workers under them.
See the demo.
Results:
| managercode | name | age |
| ----------- | ------ | --- |
| 1 | Chris | 52 |
| 1 | Phil | 40 |
| 1 | Harry | 33 |
| 2 | Rick | 55 |
| 2 | Johnny | 28 |
| 2 | Jeff | 47 |

Filter out distinct records and leave last one

I have database that contains some distinct values like below
id firstName lastName someOption
1 mark tom 28
2 jack bob 75
3 mark tom 48
4 mark tom 87
5 sara tim 64
6 jack bob 23
7 katy jimmy 65
I want to select all the table but filter out distinct records instead of the last one like this
id firstName lastName someOption
4 mark tom 87
5 sara tim 64
6 jack bob 23
7 katy jimmy 65
How to achieve this with sql?
One method is a correlated subquery:
select t.*
from t
where t.id = (select max(t2.id)
from t t2
where t2.firstname = t.firstname and t2.lastname = t.lastname
);
With an index on (lastname, firstname, id), this is probably the fastest method on larger amounts of data.
With NOT EXISTS:
select t.* from tablename t
where not exists (
select 1 from tablename
where (firstName, lastName) = (t.firstName, t.lastName) and id > t.id
)
See the demo.
Results:
| id | firstName | lastName | someOption |
| --- | --------- | -------- | ---------- |
| 4 | mark | tom | 87 |
| 5 | sara | tim | 64 |
| 6 | jack | bob | 23 |
| 7 | katy | jimmy | 65 |

MySQL query that needs a lot of (complex?) filtering

I have the following database table (People):
+--------+--------+--------+
| Name | Age | Time |
+--------+--------+--------+
| Tim | 30 | 10:10 |
| Jill | 31 | 10:20 |
| Peter | 31 | 10:30 |
| Peter | 33 | 10:40 |
| Jack | 32 | 10:50 |
| Susan | 35 | 10:60 |
| Susan | 35 | 11:70 |
+--------+--------+--------+
Now I want to get 5 names which are the oldest from this list:
Select * FROM People ORDER BY Age DESC LIMIT 5
This will give:
| Susan | 35 | 11:70 |
| Susan | 35 | 10:60 |
| Peter | 33 | 10:40 |
| Jack | 32 | 10:50 |
| Peter | 31 | 10:30 |
Now this is not exactly what I want. We see Susan in there twice, same as Peter. I don't want duplicate names to show up. Now we see that the 2 Susans have both the same age, so the Susan with the highest time (mm:ss) should be filter out (in this case: | Susan | 35 | 11:70 |)
Fot the 2 Peters we see that one Peter is older, so in this case the younger Peter should be filtered out (| Peter | 31 | 10:30 |)
So how would this Query look like? It should first select all, then order them by Age (oldest on top), then filter out the duplicate names where it must first look at the age (lowest gets filtered) and then at the time (highest time gets filter out) and then DESC LIMIT 5.
So the only correct result will look like this:
| Susan | 35 | 10:60 |
| Peter | 33 | 10:40 |
| Jack | 32 | 10:50 |
| Jill | 31 | 10:20 |
| Peter | 31 | 10:30 |
SELECT
Name, Age, MIN(Time) As LowestTime
FROM
People
GROUP BY
Name, Age
ORDER BY
Age DESC, Name ASC
LIMIT 5
SELECT Name,Age,Max(Time) as Time
FROM People
GROUP BY concat(Age,':',Name)
ORDER BY Age DESC,Time ASC
LIMIT 5
The GROUP BY takes care of Susan, the ORDER BY of Peter
I believe this query is what you're looking for. It filters by Name:Age, then Name:Time, and finally does a final group by Name and ORDER as necessary.
Query
SELECT `Name`, `Age`, `Time`
FROM `People`
WHERE concat(`Name`,'-',`Time`)
IN (
SELECT concat(`Name`,'-',MAX(`Time`))
FROM `People`
WHERE concat(`Name`,'-',`Age`)
IN (
SELECT concat(`Name`,'-',MIN(`Age`))
FROM `People`
GROUP BY `Name`
)
GROUP BY `Name`
)
GROUP BY `Name`
ORDER BY `Age` DESC
LIMIT 5
Note: While this is a valid query and returns the results you're looking for, it can get pretty expensive, especially with a larger table. If you plan to do this filtering on a larger table, I would suggest adding a column where you concatenate these fields manually, and set up an index against both columns. Also, I'm assuming this was just a quick example, but if you should also have an id column set up that is PRIMARY and auto_increment.