Select distinct pairs in SQL - mysql

For this table each column has distinct rows i.e count(Name) = count(Spouse_Name) = count(*)
Want to write a SQL query where pairs (Name and Spouse_Name) are distinct i.e Alex Sandra and Sandra Alex are same.
The output should be following:
Note: Self Inner Join if possible.

Untested:
select distinct t1.name, t1.spouse_name
from table t1
inner join table t2
on concat(t1.name, t1.spouse_name) = concat(t2.spouse_name, t2.name)
I couldn't find the table name in your post so I used the name table.

Assuming that name and spouse_name will never be equal in the same row you can use NOT EXISTS like this:
select t.*
from tablename t
where t.name < t.spouse_name
or not exists (
select 1 from tablename
where name = t.spouse_name and spouse_name = t.name
)
This code will work in any database since it uses standard SQL.
For MySql and this sample data you can do this self join:
select distinct
least(t1.name, t1.spouse_name) name,
greatest(t1.name, t1.spouse_name) spouse_name
from tablename t1 inner join tablename t2
on t1.name = t2.spouse_name and t2.name = t1.spouse_name
Although the same results can be obtained without a join:
select distinct
least(t1.name, t1.spouse_name) name,
greatest(t1.name, t1.spouse_name) spouse_name
from tablename t1
And another query with a self join:
select t1.name, t1.spouse_name
from tablename t1 inner join tablename t2
on t2.spouse_name = t1.name and t2.name = t1.spouse_name
where t1.name < t1.spouse_name

Related

MySQL select a set of columns with more than one variation in another column

table looks like this:
id group name
1 1 A
2 1 A
3 2 A
4 2 B
5 3 A
I want to select the rows with more than one distinct names in the same group. The result should be the following:
id group name
3 2 A
4 2 B
Any idea how do achieve this?
You can get the groups with aggregation:
select group
from t
group by group
having min(name) <> max(name);
You can get the original rows using join, in, or exists:
select t.*
from t
where t.group in (select group
from t
group by group
having min(name) <> max(name)
);
Note: group is a lousy name for a column because it is a SQL keyword and a MySQL reserved word.
You could do it with a correlated subquery:
SELECT t1.id, t1.group, t1.name
FROM mytable AS t1
WHERE EXISTS (
SELECT * FROM mytable t2
WHERE t2.group=t1.group AND t2.name <> t1.name
);
Or you could do it by counting distinct names in the group:
SELECT t1.id, t1.group, t2.name
FROM mytable AS t1
INNER JOIN (
SELECT t2.group FROM mytable AS t2
GROUP BY t2.group HAVING COUNT(DISTINCT t2.name) > 1
) AS t2 USING (group);

SQL: full outer join (ambitious column name)

I have two table, t1 and t2.
-- t1
id name address
1 Tim A
2 Marta B
-- t2
id name address
1 Tim A
3 Katarina C
If I do t1 full outer join with t2
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
However, the result has ambitious id, name, address.
How do I rename this so that I don't have duplicate column name?
Attempt:
SELECT name, address FROM
(SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id) as derived_table;
return: ERROR- duplicate column name "name".
Ditch the * in the SELECT list.
Specify the list of expressions to be returned. And qualify all column references with either the table name, or preferably, a shorter table alias.
And assign an alias to the expression and that will be the name of the column in the resultset.
Also, the query shown is not equivalent to a FULL OUTER JOIN.
If the goal is return all rows from t1, and to also return rows from t2 where a matching row doesn't exist in t1, I'd do something like this...
SELECT t.id AS t_id
, t.name AS t_name
, t.addr AS t_addr
FROM t1 t
UNION ALL
SELECT s.id
, s.name
, s.addr
FROM t2 s
LEFT
JOIN t1 r
ON r.id = s.id
WHERE r.id IS NULL
Try fully qualifying it like
SELECT t1.id, t1.name, t1.address FROM t1

SQL Query to display employee who is a supervisor from employee table

I am in this dilemma: here is a table with records.
The last column has supervisors and it refers to the first column.
How can I select all employees who are supervisors and display for each, first name and last name?
Here is the table
You can use EXISTS to do this(preferred approach)
SELECT *
FROM yourtable t1
WHERE EXISTS (SELECT 1
FROM yourtable t2
WHERE t1.EMPLOYEEID = t2.EMPSUPERVISOR)
using IN operator
SELECT *
FROM yourtable t1
WHERE t1.EMPLOYEEID IN (SELECT t2.EMPSUPERVISOR
FROM yourtable t2)
using JOIN
SELECT t1.*
FROM yourtable t1
JOIN (SELECT DISTINCT EMPSUPERVISOR
FROM yourtable) t2
ON t1.EMPLOYEEID = t2.EMPSUPERVISOR
I would say:
SELECT EMPLNAME , EMPLFNAME
FROM THETABLE
WHERE EMPLOEEID IN (SELECT DISTINCT EMPSUPERVISOR
FROM THETABLE
)
;

Display all employees working on all of the projects?

table 1 includes employee name and their initials
table 2 includes projectnumber and pmember(initials as well)
we only have to display the name of the employees so i have to use a WHERE clause, which i can't construct :( here's what i've done so far. it only returns 1 employee (correct answer is 2 employees)
select t1.name
from t1
where t1.initials IN (select t2.pmember
from t2
having count(t2.projectnumber) > 1)
thanks in advance!
select t1.name
from t1
left join t2 on t1.initials = t2.pmember
group by t1.name
having sum(t2.projectnumber is null) = 0
This query should give you the names of the members working on all projects:
SELECT T1.NAME
FROM T1
JOIN T2 ON T1.INITIALS = T2.PMEMBER
GROUP BY T1.NAME
HAVING COUNT(T2.PROJECTNUMBER) = (SELECT COUNT(1) FROM T2 T2ALIAS)
Maybe this query helps you:
SELECT T1.NAME
FROM T1
INNER JOIN T2 ON T1.INITIALS = T2.PMEMBER
HAVING COUNT(T2.PROJECTNUMBER) > 1
To show all emp that works on all projects, you need a distinct count like this, I think:
SELECT NAME FROM T1 WHERE INITIALS IN (
SELECT PMEMBER FROM T2 HAVING DISTINCT COUNT(PROJECTNUMBER) = (
SELECT DISTINCT COUNT(PROJECTNUMBER) FROM T2)
GROUP BY PMEMBER)

mysql output to a value in the same table using a primary key with subselect

for example, how do i refer to the name son. when all i have is the mothers name USING subselect
id-Name - mother
1 -son - 2
2 -mommy - null
This is using a subselect.
SELECT t.*,
(SELECT Name FROM TABLE_NAME WHERE mother = t.id) as sons_name
FROM TABLE_NAME as t
WHERE t.name = 'Mommy'
But you could do it using a join also:
SELECT t1.*, t2.name as sons_name
FROM TABLE_NAME as t1
LEFT JOIN TABLE_NAME as t2 ON t2.mother = t1.id
WHERE t1.name = 'Mommy'