Get distinct records from 2 union sql statement - mysql

I would like to seek the advice of some sql experts.
I wrote sql statement for getting authors names from staff and alumni table. Some author's name will be in both tables. So the logic is if the author name is in staff, use that otherwise look for alumni table.
Here is my sql statement, seems fine but it is showing same author name from both staff and alumni table.
SELECT DISTINCT AP.Author_name, P.people_id, P.Name, P.Journal_name, AP.Author_sortorder FROM `Paper_Author` AS AP LEFT JOIN `People` AS P ON ( AP.Author_id = P.people_id ) WHERE AP.Paper_id =3838
UNION
SELECT DISTINCT AN.Author_name, N.People_id, N.Name, N.Journal_name, AN.Author_sortorder FROM `Paper_Author` AS AN LEFT JOIN `Alumni` AS N ON ( AN.Author_id = N.People_id ) WHERE AN.Paper_id =3838 ORDER BY Author_sortorder LIMIT 0 , 30
Result:
people_id-- Author_name-- Journal_name--
1 Name1 A1
2 Name2 B1
3 Name3 C1
3 Name3 C1
4 Name4 D
4 Name4
Expected Result :
people_id-- Author_name-- Journal_name--
1 Name1 A1
2 Name2 B1
3 Name3 C1
4 Name4 D

This can probably be solved by an additional select using the original result as a subquery
SELECT DISTINCT * FROM (
SELECT DISTINCT AP.Author_name, P.people_id, P.Name, P.Journal_name, AP.Author_sortorder FROM `Paper_Author` AS AP LEFT JOIN `People` AS P ON ( AP.Author_id = P.people_id ) WHERE AP.Paper_id =3838
UNION
SELECT DISTINCT AN.Author_name, N.People_id, N.Name, N.Journal_name, AN.Author_sortorder FROM `Paper_Author` AS AN LEFT JOIN `Alumni` AS N ON ( AN.Author_id = N.People_id ) WHERE AN.Paper_id =3838 ORDER BY Author_sortorder LIMIT 0 , 30
);

The difficulty with this problem is that you might need information from either the People or Alumni tables. We would like to just join to a single table containing the right information. Much of the complexity of the below query is in creating a table which contains the right metadata for each person.
SELECT
pa.Author_name,
pa.Author_sortorder,
t1.people_id,
t1.Name,
t1.Journal_name
FROM Paper_Author pa
LEFT JOIN
(
SELECT people_id, Name, Journal_name, 0 AS source
FROM People
UNION ALL
SELECT people_id, Name, Journal_name, 1
FROM Alumni
) t1
ON pa.Author_id = t1.people_id
INNER JOIN
(
SELECT people_id, MIN(source) AS source
FROM
(
SELECT people_id, 0 AS source
FROM People
UNION ALL
SELECT people_id, 1
FROM Alumni
) t
GROUP BY people_id
) t2
ON t1.people_id = t2.people_id AND
t1.source = t2.source
WHERE
pa.Paper_id = 3838;

Related

symmetric pair in sql

Given the tables student, mathematics_marks, science_marks
student
student_id (Primary Key) | smallint
student_name | varchar(30)
mathematics_marks
student_id (Primary Key) | smallint
score | float (5,2)
science_marks
student_id (Primary Key) | smallint
score | float (5,2)
A student is called as being a part of a symmetric pair if the marks obtained by that student in science is equal to the marks obtained by some other student in mathematics and the marks obtained in mathematics are the same as marks obtained by the other student in science.
Write a SQL query to print the name of the students who are a part of the symmetric pair. Order the output in order of student name.
with cte as (
select m.student_id, m.score as math_score, s.score as science_score
from mathematics_marks m inner join science_marks s
on s.student_id = m.student_id
)
select s1.student_name
from cte c1 inner join cte c2
on c2.student_id > c1.student_id and c2.math_score = c1.science_score and c1.math_score = c2.science_score
inner join student s1 on s1.student_id = c1.student_id and s1.student_id = c2.student_id
need to get the pair in two different rows?
EDITED:
answer to this
with cte as (
select m.student_id, m.score as math_score, s.score as science_score
from mathematics_marks m inner join science_marks s
on s.student_id = m.student_id
),
T as (select c1.student_id, c1.math_score, c1.science_score, s.student_name as name
from cte c1 inner join student s
on c1.student_id = s.student_id )
select t1.name from T t1 inner join T t2
on t1.math_score = t2.science_score and
t1.science_score = t2.math_score
order by t1.name
A properly designed schema would have a single table for student, subject, and mark. The first step then is to emulate that table, which could be as follows:
SELECT student_id
, 'mathematics' subject
, score
FROM mathematics_marks
UNION
SELECT student_id
, 'science'
, score
FROM science_marks
For further help, see: Why should I provide an MCRE for what seems to me to be a very simple SQL query?
It's always easy to answer if the post is accompanied by sample data and expected output . Are you looking for somthing like this
Select student.student_id
,maths.score maths_socer
,sci.score science_score
from
(
Select 1 student_id union all
Select 2 union all
Select 3
) student
Join
(
Select 1 student_id, 20 score union all
Select 2, 30 union all
Select 3, 40
) maths
on maths.student_id=student.student_id
Join
(
Select 1 student_id , 30 score union all
Select 2,20 union all
Select 3,40
) sci on sci.student_id !=student.student_id
Where sci.score = maths.score

LEFT JOIN with GROUP BY with WHERE clause and also with OR in sql

I have 3 tables:
Table 1 - "taxonomy_index" where we have 4 columns(Columns are nid,tid,sticky,created)
Table 2 - "node" where we have 15 columns(columns are nid, vid,type etc... )
Table 3 - "taxonomy_term_data" where we have 6 columns (columns are tid, vid, name etc..)
I want to join these 3 tables and also there is some condition.
I know the individual queries but i want to set all the queries into one and form one join
Query 1
SELECT count(*), tid
FROM taxonomy_index
GROUP BY tid HAVING COUNT(*) >3
This query gives me two values, one is count and other is tid. ie how many times the tid are used .
Query 2
select *
from node
where type='book' OR type='student'
OR type='teacher' OR type='class';
here i will get the node which is associated to these content types.
I want to join 3 tables. In output i want to get how many times each tid used(query 1) and where types(query 2) and get tid name from taxonomy_term_data.
Count, tid,name where for given types
Ok, suppose you can join on tid each time, you could possibly use the following syntax. Note that the CTE is not compulsary here, I just find them useful for readability.
;WITH CTE_Count AS
(
SELECT count(*) AS Count, tid
FROM taxonomy_index
GROUP BY tid HAVING COUNT(*) >3
)
, CTE_Node AS
(select *
from node
where type='book' OR type='student'
OR type='teacher' OR type='class' )
, CTE_TermData AS
(SELECT * FROM taxonomy_term_data)
SELECT CC.tid, CC.Count, CN.Node, CT.tid_Name
FROM CTE_Count AS CC
INNER JOIN CTE_Node AS CN ON CN.tid = CC.tid
INNER JOIN CTE_TermData AS CT ON CT.tid = CC.tid
SELECT distinct t1.TID, t3.name, cntt1.count from taxonomy_index t1
inner join
(
SELECT count(*) as 'count', t1.tid
FROM taxonomy_index t1
GROUP BY t1.tid HAVING COUNT(*) >3
) cntt1 on t1.tid = cntt1.tid
inner join node t2 on t1.nid = t2.nid and (type='book' OR type='student' OR
type='teacher' OR type='class')
inner join taxonomy_term_data t3 on t1.tid = t3.tid

Couldn't Create the Expected Query

I am new in Sql Could you please help it with this problem.
id |name |reportingTo
----------------------
1 A NULL
2 B 1
3 C 1
4 D 2
5 E 2
6 F 5
I want the expected output as below. How i can impliment this with one query.
Output
------------------------
Name Reporter
A No One
B A
C A
D B
E B
F E
I have tried this but not working
select name,(case when reporting = null then 'MD'
ELSE (select a.name from testLevel a inner join testLevel b on a.id=b.reporting where a.id=b.reporting)
END) reportingto
From testLevel
Thanks In-advance..
Keep joins and subselects out of your select statement.
MySQL and Oracle are two seperate databases...choose on or the other
select a.name, b.name
from reportingto a left join reportingto b on a.id = b.reportingto
that will give names..use a isnull statement to resolve the 'no one' when bnot found. Note the left join makes this possible, an inner join won't work here.
select a.name, isnull(b.name, 'No One')
from reportingto a left join reportingto b on a.id = b.reportingto
How about a self join? So something like
SELECT r.Name ,
rTo.Name Reporter
FROM testLevel r LEFT JOIN
testLevel rTo ON r.ReportingTo = rTo.id
Based on the fact that you have picked 3 RDBMSs you might want to take a look at
MySQL IFNULL:
IFNULL(rTo.Name, 'No One') Reporter
SQL Server ISNULL
ISNULL(rTo.Name, 'No One') Reporter
In SQL Server:
You can also achieve this by using a Common Table Expression:
WITH CTE (
SELECT DISTINCT reportingTo, name
FROM testLevel
)
SELECT DISTINCT A.name AS Name, ISNULL(B.name, 'No One') AS Reporter
FROM testLevel A
LEFT JOIN CTE B ON A.id = B.reportingTo
Or using a subquery:
SELECT DISTINCT A.name AS Name, ISNULL(B.name, 'No One') AS Reporter
FROM testLevel A
LEFT JOIN (
SELECT DISTINCT reportingTo, name
FROM testLevel
) B ON A.id = B.reportingTo

MS SQL to MySQLconversion - Recursive CTE

i'm trying to convert this MsSQL to MySQL any idea how this can be done?
WITH Hierarchy(id, ciid1, name, parent, myLevel)
AS (SELECT id,
ciid1,
name,
parent,
0 AS myLevel
FROM cities_new c
WHERE c.id = 2222
UNION ALL
SELECT c.id,
c.ciid1,
c.name,
c.parent,
ch.myLevel + 1
FROM cities_new c
INNER JOIN Hierarchy ch
ON c.parent = ch.ciid1)
SELECT count(id) AS total
FROM hotels_new
WHERE id NOT IN( 69912, 70717, 75347 )
AND ciid IN(SELECT id
FROM Hierarchy)

union on certain columns created from join?

The trouble I've been having with union is that the tables your querying must have all the same columns. Is there a way to query using an join with a union on ONLY certain coloumns?
SELECT Client.Client_ID, Client.First_Name, Client.Last_Name, Client.Company_Name from Client
union
select Agency_Employee.Employee_ID, Agency_Employee.First_Name, Agency_Employee.Last_Name, ''
from Agency_Employee
union
select Agency_ID, '', '', Agency_Name from Admin_Agency
SELECT proj.ProjectID, A.Project_Title, B.Account_ID, B.Username, B.Access_Type FROM Project_Assigned proj
JOIN Account B
ON proj.AccountID = B.Account_ID
JOIN Project A
ON proj.ProjectID = A.Project_ID
WHERE proj.ProjectID = 1;
In the above above I'm trying to combine a join query created which matches accounts assigned to project 1 and with union I'm trying to get additional information such as first_name, last_name from those account numbers from different tables such as client, agency_employee.
Yes it is.
You can do it by specifying the names of the columns- they should be the same.
In your case you can do it like that:
SELECT Client.Client_ID, Client.First_Name, Client.Last_Name, Client.Company_Name from Client
union
select Agency_Employee.Employee_ID as Client_ID, Agency_Employee.First_Name, Agency_Employee.Last_Name, '' as Company_Name
from Agency_Employee
union
select Agency_ID as Client_ID, '' as First_Name, '' as Last_Name, Agency_Name as Company_Name from Admin_Agency
I don't see in your code how exactly you want to merge your union with the following queries but you can do it with sub-queries. Here is the example:
select a.item1, b.count from table_a a
inner join (
select item1, count(*) as count
from table_b
group by item1
) b on b.item1 = a.item1